为接收函数设置套接字超时
Setting socket timeout for receive function
我有一个客户端服务器连接,客户端正在向服务器发送数据。
while (1) {
bzero(buffer, 256);
sleep(1);
n = read(sock, buffer);
if(n < 0) error("ERROR reading from socket");
c = message[0];
//do something
}//close while loop
我只想等待读取发生几秒钟的问题 - 在我的代码中,如果客户端不发送任何内容,它就会卡住等待服务器读取某些内容。
请问我如何才能等待读取发生几秒钟?
您可以使用 select() api 来达到这个目的。在此api中,您可以提及select中的时间api,以秒和微秒为单位。
基本上 read
调用会尝试读取,因此如果您不想在其上获取堆栈,则必须将 sock
变量声明为非阻塞或使用 select
函数超时 (man select
)。在第一种情况下,你不能等待几秒钟,但你可以尝试阅读 k
次,然后通过。这是非阻塞套接字的示例:
/*
* Non-blocking socket solution
* just put the read in a for-loop
* if you want to read k times
*/
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
int r1;
/*Setting the socket as non-blocking*/
int flags = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, flags | O_NONBLOCK);
errno = 0; /*If the read fails it sets errno*/
if((r1=read(sock,buf_in,N))== -1) { /*If the read returns an error*/
if(errno != EAGAIN && errno != EWOULDBLOCK){ /*If the error is not caused by the non-blocking socket*/
perror("Error in read\n");
exit(EXIT_FAILURE);
}
}
这是 select 解决方案:
/*
* Select solution.
* This is not a complete solution but
* it's almost everything you've to do
*/
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/select.h>
#define SVC(r,c,e) \
errno = 0; \
if((r=c)==-1) { perror(e);exit(errno); }
int r = 0;
int fd_skt;
fd_set rdset;
fd_set set;
struct timeval tv; /*Timer structure*/
int fd_num_max = 0; /*Maximum opened file descriptor*/
if(fd_skt > fd_num_max) fd_num_max = fd_skt;
FD_ZERO(set);
FD_SET(fd_skt,set); /*fd_skt is where you're waiting for new connection request*/
/*Setting the timer*/
tv.tv_sec = 0;
tv.tv_usec = 200*1000;
rdset = set;
SVC(r,select((fd_num_max+1),(&rdset),NULL,NULL,&tv),"Unable to select\n");
如果您的套接字是非阻塞的,您可以使用 select 函数。
如果您的套接字阻塞,您可以使用 setsockopt function. See this Whosebug question for more details. Linux: is there a read or recv from socket with timeout?
设置读取超时
我有一个客户端服务器连接,客户端正在向服务器发送数据。
while (1) {
bzero(buffer, 256);
sleep(1);
n = read(sock, buffer);
if(n < 0) error("ERROR reading from socket");
c = message[0];
//do something
}//close while loop
我只想等待读取发生几秒钟的问题 - 在我的代码中,如果客户端不发送任何内容,它就会卡住等待服务器读取某些内容。
请问我如何才能等待读取发生几秒钟?
您可以使用 select() api 来达到这个目的。在此api中,您可以提及select中的时间api,以秒和微秒为单位。
基本上 read
调用会尝试读取,因此如果您不想在其上获取堆栈,则必须将 sock
变量声明为非阻塞或使用 select
函数超时 (man select
)。在第一种情况下,你不能等待几秒钟,但你可以尝试阅读 k
次,然后通过。这是非阻塞套接字的示例:
/*
* Non-blocking socket solution
* just put the read in a for-loop
* if you want to read k times
*/
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
int r1;
/*Setting the socket as non-blocking*/
int flags = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, flags | O_NONBLOCK);
errno = 0; /*If the read fails it sets errno*/
if((r1=read(sock,buf_in,N))== -1) { /*If the read returns an error*/
if(errno != EAGAIN && errno != EWOULDBLOCK){ /*If the error is not caused by the non-blocking socket*/
perror("Error in read\n");
exit(EXIT_FAILURE);
}
}
这是 select 解决方案:
/*
* Select solution.
* This is not a complete solution but
* it's almost everything you've to do
*/
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/select.h>
#define SVC(r,c,e) \
errno = 0; \
if((r=c)==-1) { perror(e);exit(errno); }
int r = 0;
int fd_skt;
fd_set rdset;
fd_set set;
struct timeval tv; /*Timer structure*/
int fd_num_max = 0; /*Maximum opened file descriptor*/
if(fd_skt > fd_num_max) fd_num_max = fd_skt;
FD_ZERO(set);
FD_SET(fd_skt,set); /*fd_skt is where you're waiting for new connection request*/
/*Setting the timer*/
tv.tv_sec = 0;
tv.tv_usec = 200*1000;
rdset = set;
SVC(r,select((fd_num_max+1),(&rdset),NULL,NULL,&tv),"Unable to select\n");
如果您的套接字是非阻塞的,您可以使用 select 函数。 如果您的套接字阻塞,您可以使用 setsockopt function. See this Whosebug question for more details. Linux: is there a read or recv from socket with timeout?
设置读取超时