带recv-timeout的套接字:这段代码有什么问题?

我试图实现一个接收超时1秒的套接字

int sockfd; struct sockaddr_in self; struct sockaddr_in client_addr; int addrlen=sizeof(client_addr); ssize_t nBytes; sockfd = socket(AF_INET, SOCK_STREAM, 0); self.sin_family = AF_INET; self.sin_port = htons(PORT); self.sin_addr.s_addr = INADDR_ANY; int on = 1; setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on); // 1 Sec Timeout tv.tv_sec = 1; tv.tv_usec = 0; setsockopt( sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv); bind(sockfd, (struct sockaddr*)&self, sizeof(self)); listen(sockfd, 20); clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &addrlen); nBytes = recv(clientfd, buffer, MAXBUF-1, 0); 

没有'setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,&t​​v,sizeof(tv);'调用accept和recv工作,但recv块。

'setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,&t​​v,sizeof(tv);'接受调用产生错误'资源暂时不可用'。

有人可以告诉我这种方法有什么问题吗?

你想在哪个套接字上有一秒超时? 接受连接的人,还是accept()建立的人?

我会假设后者 – 所以尝试在接受返回后设置clientfd上的接收超时。 你也可以到你需要使用select的地方,但是你不需要。

这是有点题外话,但我真的想分享这个解决方案设置在Windows和UNIX的recv超时。 也许是我,但是花了我很多时间来弄清楚为什么我的程序不工作,以及如何正确设置超时。 希望你觉得它有用。 它将超时设置为10秒。

对于Windows:

 DWORD sock_timeout = 10*1000; 

对于Unix:

 const struct timeval sock_timeout={.tv_sec=10, .tv_usec=0}; 

对彼此而言:

 setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&sock_timeout, sizeof(sock_timeout)); 

这是一个使用select的片段:

 FD_ZERO(&masterfds); FD_SET(sockfd,&masterfds); memcpy(&readfds,&masterfds,sizeof(fd_set)); timeout.tv_sec = 2; timeout.tv_usec = 0; if (select(sockfd+1, &readfds, NULL, NULL, &timeout) < 0) { printf("select error"); exit(1); } if (FD_ISSET(sockfd, &readfds)) { //printf("Read from socket\n"); // read from the socket res = recvfrom(sockfd, (char *)hdrbuf, sizeof(hdrbuf), MSG_PEEK, recvaddr, address_len); } else { // the socket timedout //printf("Socket timeout started=%d\n",packets_started); 

什么是错的…错误代码EAGAIN(资源暂时不可用)正是你应该在超时过期后得到的!

在这两条线的每一条上都需要一个右括号。

 - setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on); + setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); - setsockopt( sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv); + setsockopt( sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); 

在调用recv()或accept()之前尝试使用select()。

select()接受一个文件描述符数组(包括套接字),并在至少有一个准备接收的时候返回。 它也可以在超时返回。

在Linux中,你也可以尝试poll()(不知道Winsock是否提供了这个)。