[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()
errno
EINTR
답변
리눅스
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()
적절한 실행을 위해 함수 호출 전에이 설정을 지정했습니다.