选择不等待 C++ 套接字中的超时值
select does not wait for timeout value in c++ sockets
我编写了一个服务器代码,它接受来自客户端的新客户端和数据。但问题是,尽管没有来自客户端的数据,但选择不会等到超时。我想等待 5 秒钟并为可用客户端发送心跳。但它在第一次迭代中等待 5 秒,然后在下一次迭代中快速发送检测信号。如何解决这个问题。提前谢谢。
void * Communicate(void * id)
{
int *iSockID = (int *) id;
int listener = *iSockID;
fd_set master; // master file descriptor list
fd_set read_fds; // temp file descriptor list for select() read
fd_set write_fds; // temp file descriptor list for select() read
int fdmax; // maximum file descriptor number
int i, j, rv;
FD_ZERO(&master); // clear the master and temp sets
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
// add the listener to the master set
FD_SET(listener, &master);
printf("Listener is %d n" , listener);
// keep track of the biggest file descriptor
fdmax = listener; // so far, it's this one
//accept 3 clients
// main loop
for(;;) {
read_fds = master; // copy it
write_fds = master;
struct timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 0;
int iResult = select(fdmax+1, &read_fds, &write_fds, NULL, &tv) ;
if (iResult == -1)
{
perror("select");
exit(4);
}
for(i = 0; i <= fdmax; i++)
{
//send work for clients
SendHeartBeats(write_fds , fdmax , listener , i );
}
// run through the existing connections looking for data to read
// ADD NEW CONNECTIONS READ FROM CONNECTIONS
for(i = 0; i <= fdmax; i++)
{
if (FD_ISSET(i, &read_fds))
{ // we got one!!
// handle new connections
if (i == listener)
{
AcceptNewClients(master , fdmax , listener );
} else
{
AccepeDataFromClients(i , master);
} // END handle data from client
} // END got new incoming connection
} // END looping through file descriptors
sleep(3);
} // END for(;;)
return 0;
}
不能按等于fd_set变量。 您需要使用FD_COPY。 如果不这样做,则只需将句柄复制到实际数据,该句柄已标记为已完成。
您需要
更改代码以在每次调用select()
时重新初始化read_fd
和write_fd
变量,因为它会在退出时修改它们,因此每次都需要重置它们。 正如其他人所说,使用 =
运算符复制 master
变量并不是复制fd_set
结构的正确方法。
试试这个:
void * Communicate(void * id)
{
int *iSockID = (int *) id;
int listener = *iSockID;
fd_set master; // master file descriptor list
fd_set read_fds; // temp file descriptor list for select() read
fd_set write_fds; // temp file descriptor list for select() read
struct timeval tv;
int fdmax; // maximum file descriptor number
int i, j, rv;
printf("Listener is %d n", listener);
// add the listener to the master set
FD_ZERO(&master);
FD_SET(listener, &master);
// keep track of the biggest file descriptor
fdmax = listener; // so far, it's this one
//accept 3 clients
// main loop
clock_t c1 = clock();
while (1)
{
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
#ifdef MSWINDOWS
// Windows does not have FD_COPY()
for (u_int i = 0; i < master.fd_count; ++i)
{
FD_SET(master.fd_array[i], &read_fd);
FD_SET(master.fd_array[i], &write_fd);
}
#else
FD_COPY(&master, &read_fd);
FD_COPY(&master, &write_fd);
#endif
tv.tv_sec = 1;
tv.tv_usec = 0;
int iResult = select(fdmax+1, &read_fds, &write_fds, NULL, &tv);
if (iResult == -1)
{
perror("select");
exit(4);
}
clock_t c2 = clock();
if (((c2-c1) / CLOCKS_PER_SEC) >= 5)
{
c1 = c2;
for(i = 0; i <= fdmax; i++)
{
if ((i != listener) && FD_ISSET(i, &write_fds))
{
//send work for client
SendHeartBeat(i);
}
}
}
// run through the existing connections looking for data to read
// ADD NEW CONNECTIONS READ FROM CONNECTIONS
for(i = 0; i <= fdmax; i++)
{
if (FD_ISSET(i, &read_fds))
{
// we got one!!
if (i == listener)
{
AcceptNewClient(master, fdmax, listener);
}
else
{
AcceptDataFromClient(i);
}
}
}
}
return 0;
}
您在评论中指出您正在使用Linux 2.6.27
.由于在 Linux 中,fd_set
是包含整型数组的结构,因此使用赋值将master
复制到read_fds
就可以了。
您的select
调用未阻塞的原因是,您正在初始化read_fds
和write_fds
master
。您的空闲客户端套接字始终是可写的,因此您会立即醒来。顺便说一句,选择在listener
套接字上可写是没有意义的。
只有在尝试写入但收到 EAGAIN
/EWOULDBLOCK
错误时,才应在write_fds
中设置客户端套接字。
相关文章:
- 为什么我在蓝牙连接()上收到"java.io.IOException:读取失败,套接字可能关闭或超时,读取re
- UDP 套接字 select() 在某些情况下无延迟(超时)返回 1
- Linux 套接字 recv 返回 -1,errno 110 连接超时
- 为什么 Windows udp 接收套接字上的超时总是比 SO_RCVTIMEO 设置的长 500 毫秒
- 如何设置超时以在C套接字上"connect()"功能?
- 如何通过超时检查Boost ASIO套接字中的数据
- c tcp套接字非阻塞接收超时
- C++中的Bittorrent客户端,在非阻塞套接字上连接到对等端总是超时
- 多线程套接字超时
- 客户端套接字连接() 在服务器 accept() 超时后成功
- 正在设置套接字超时
- 套接字SO_RCVTIMEO超时是C++/VC++中设置值的两倍
- 如何在Unix上的c++套接字上使用带有read()的超时
- 套接字连接超时因网络而异
- 管理多个UDP套接字的超时
- 在Windows上设置来自套接字的recv超时
- Boost ASIO套接字读取N字节不多不少,等待它们到来或超时异常
- 带超时的多线程面向对象套接字代码
- 正在获取套接字函数的连接超时
- 从一组套接字中检测超时套接字