수색…


소개

IO가 차단 / 비 차단 및 동기 / 비동기 일 수 있습니다. POSIX API는 동기식 블로킹 API (예 : 고전적인 읽기, 쓰기, 전송, recv 호출), 동기 논 블로킹 API (동일한 기능, O_NONBLOCK 플래그 및 IO 멀티플렉싱 호출로 열린 파일 설명자) 및 비동기 API ( aio_ 시작하는 함수)를 제공합니다.

동기식 API는 일반적으로 "fd 당 하나의 스레드 / 프로세스"스타일과 함께 사용됩니다. 이것은 자원에 끔찍합니다. 비 차단 API는 한 스레드에서 fds 집합과 함께 작동 할 수 있습니다.

투표

이 예제에서 우리는 연결된 소켓 쌍을 만들고 하나에서 다른 문자열로 4 개의 문자열을 보내고받은 문자열을 콘솔에 출력합니다. 우리가 send를 호출 할 횟수는 우리가 recv를 호출 한 횟수와 같지 않을 수도 있습니다.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>

#define BUFSIZE 512

int main()
{    
    #define CKERR(msg) {if(ret < 0) { perror(msg); \
        close(sockp[0]); close(sockp[1]); exit(EXIT_FAILURE); } }
    const char* strs_to_write[] = {"hello ", "from ", "other ", "side "};
    
    int sockp[2] = {-1, -1};
    ssize_t ret = socketpair (AF_UNIX, SOCK_STREAM, 0, sockp);
    CKERR("Socket pair creation error")
    
    struct pollfd pfds[2];
    for(int i=0; i<2; ++i) {
        pfds[i] = (struct pollfd){sockp[i], POLLIN|POLLOUT, 0};
        fcntl(sockp[i], F_SETFL|O_NONBLOCK); // nonblocking fds are
                // literally mandatory for IO multiplexing; non-portable
    }
    char buf[BUFSIZE];
    
    size_t snt = 0, msgs = sizeof(strs_to_write)/sizeof(char*);
    while(1) {
        int ret = poll(pfds,
            2 /*length of pollfd array*/,
            5 /*milliseconds to wait*/);
        CKERR("Poll error")

        if (pfds[0].revents & POLLOUT && snt < msgs) {
            // Checking POLLOUT before writing to ensure there is space
            // available in socket's kernel buffer to write, otherwise we
            // may face EWOULDBLOCK / EAGAIN error
            ssize_t ret = send(sockp[0], strs_to_write[snt], strlen(strs_to_write[snt]), 0);
            if(++snt >= msgs)
                close(sockp[0]);
            CKERR("send error")
            if (ret == 0) {
                puts("Connection closed");
                break;
            }
            if (ret > 0) {
                // assuming that all bytes were written
                // if ret != %sent bytes number%, send other bytes later
            }
        }
        if (pfds[1].revents & POLLIN) {
            // There is something to read
            ssize_t ret = recv(sockp[1], buf, BUFSIZE, 0);
            CKERR("receive error")
            if (ret == 0) {
                puts("Connection closed");
                break;
            }
            if (ret > 0) {
                printf("received str: %.*s\n", (int)ret, buf);
            }
        }

    }
    close(sockp[1]);
    return EXIT_SUCCESS;
}

고르다

Select는 I / O 멀티플렉싱을 수행하는 또 다른 방법입니다. 그 중 하나는 winsock API에 존재하는 장점입니다. 게다가 리눅스에서 select ()는 sleep되지 않은 시간을 반영하여 timeout을 수정한다. 대부분의 다른 구현은 이것을하지 않습니다. (POSIX.1은 두 가지 동작 모두 허용한다.)

폴링과 셀렉트 모두 ppoll 및 pselect 대안을 가지고있어 이벤트 대기 중에 들어오는 신호를 처리 할 수 ​​있습니다. 그리고 둘 다 엄청난 양의 파일 디스크립터 (천 개 이상)로 인해 속도가 느려지므로 Linux에서 epoll 과 FreeBSD에서 kqueue 와 같은 특정 플랫폼 호출을 선택하는 것이 현명 할 것입니다. 또는 비동기 API (POSIX의 전환 aio 예 또는 IO 완료 포트와 같은 특정 일).

선택 호출의 프로토 타입은 다음과 같습니다.

int select(int nfds, fd_set *readfds, fd_set *writefds,
       fd_set *exceptfds, struct timeval *timeout);

fd_set 는 파일 디스크립터의 비트 마스크 배열이며,

nfds 는 set + 1에있는 모든 파일 설명자의 최대 수입니다.

선택 작업 스 니펫 :

fd_set active_fd_set, read_fd_set;
FD_ZERO (&active_fd_set); // set fd_set to zeros
FD_SET (sock, &active_fd_set); // add sock to the set
// # define FD_SETSIZE sock + 1
while (1) {
    /* Block until input arrives on one or more active sockets. */
    read_fd_set = active_fd_set; // read_fd_set gets overriden each time
    if (select (FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0) {
        // handle error
    }
    // Service all file descriptors with input pending.
    for (i = 0; i < FD_SETSIZE; ++i) {
        if (FD_ISSET (i, &read_fd_set)) {
            // there is data for i
    }
}

대부분의 POSIX 구현에서 디스크의 파일과 연관된 파일 디스크립터가 블로킹한다는 점에 유의하십시오. 따라서 writefds 에이 파일이 설정되어 있어도 파일에 쓰는 것은 모든 바이트가 디스크에 덤프되지 않을 때까지 차단됩니다



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow