[c] Linux : 시간 초과가있는 소켓에서 읽기 또는 수신이 있습니까?

시간 초과로 소켓에서 데이터를 읽으려면 어떻게해야합니까? 나는 select, pselect, poll, timeout 필드가 있다는 것을 알고 있지만, 그것들을 사용하면 tcp reno stack에서 “tcp fast-path”가 비활성화됩니다.

내가 가진 유일한 아이디어는 루프에서 recv (fd, …, MSG_DONTWAIT)를 사용하는 것입니다.



답변

setsockopt 함수를 사용하여 수신 작업에 대한 시간 제한을 설정할 수 있습니다.

SO_RCVTIMEO

입력 함수가 완료 될 때까지 대기하는 최대 시간을 지정하는 제한 시간 값을 설정합니다. 입력 작업이 완료 될 때까지 대기하는 시간에 대한 제한을 지정하는 초 및 마이크로 초 수로 timeval 구조를 허용합니다. 추가 데이터를받지 않고이 시간 동안 수신 작업이 차단 된 경우 데이터가 수신되지 않으면 [EAGAIN] 또는 [EWOULDBLOCK]으로 설정된 부분 카운트 또는 errno와 함께 반환됩니다. 이 옵션의 기본값은 0이며 수신 작업이 시간 초과되지 않음을 나타냅니다. 이 옵션은 timeval 구조를 취합니다. 모든 구현에서이 옵션을 설정할 수있는 것은 아닙니다.

// LINUX
struct timeval tv;
tv.tv_sec = timeout_in_seconds;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);

// WINDOWS
DWORD timeout = timeout_in_seconds * 1000;
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof timeout);

// MAC OS X (identical to Linux)
struct timeval tv;
tv.tv_sec = timeout_in_seconds;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);

보도에 따르면 Windows에서이 호출하기 전에 수행해야합니다 bind. 나는 실험을 bind통해 Linux 및 OS X에서 이전 또는 이후 에 수행 할 수 있음을 확인했습니다.


답변

다음 은 C에서 recv사용 하여 함수에 시간 초과를 추가하는 간단한 코드입니다 poll.

struct pollfd fd;
int ret;

fd.fd = mySocket; // your socket handler 
fd.events = POLLIN;
ret = poll(&fd, 1, 1000); // 1 second for timeout
switch (ret) {
    case -1:
        // Error
        break;
    case 0:
        // Timeout 
        break;
    default:
        recv(mySocket,buf,sizeof(buf), 0); // get your data
        break;
}


답변

// WINDOWS에 대한 바인드 작업 후에도 작동합니다.

DWORD timeout = timeout_in_seconds * 1000;
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof timeout);


답변

에 대한 처리기를 설치 한 SIGALRM다음 일반 차단 전에 alarm()또는 사용하십시오 . 알람이 울리면은 로 설정된 오류를 반환합니다 .ualarm()recv()recv()errnoEINTR


답변

리눅스

struct timeval tv;
tv.tv_sec = 30;        // 30 Secs Timeout
tv.tv_usec = 0;        // Not init'ing this can cause strange errors
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv,sizeof(struct timeval));

WINDOWS

DWORD timeout = SOCKET_READ_TIMEOUT_SEC * 1000;
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));

참고 : bind()적절한 실행을 위해 함수 호출 전에이 설정을 지정했습니다.


답변