Select()有时不会等待
Select() sometimes does not wait
我正在写一个聊天程序,我的接收函数有时根本不等待。。这是接收代码:重要的部分基本上是前半部分,但我添加了整个功能,以防万一。(编辑:评论是给我自己的,不是给你们阅读的笔记!对不起!)
ReceiveStatus Server::Receive(PacketInternal*& packetInternalOut)
{
fd_set fds ;
int n ;
struct timeval tv ;
// Set up the file descriptor set.
FD_ZERO(&fds) ;
FD_SET(*p_socket, &fds) ;
// Set up the struct timeval for the timeout.
tv.tv_sec = NETWORKTIMEOUTSEC ;
tv.tv_usec = NETWORKTIMEOUTUSEC ;
// Wait until timeout or data received.
n = select ( *p_socket, &fds, NULL, NULL, &tv ) ;
if ( n == 0)
{
return ReceiveStatus::ReceiveTimeout;
}
else if( n == -1 )
{
return ReceiveStatus::ReceiveSocketError;
}
//need to make this more flexible so it can support others
sockaddr_in fromAddr;
int flags = 0;
int fromLength = sizeof(fromAddr);
char dataIn[TOTALPACKETSIZE];
int bytesIn = recvfrom(*p_socket, dataIn, TOTALPACKETSIZE, flags, (SOCKADDR*)&fromAddr, &fromLength);
// Convert fromAddr into ip, port
if(bytesIn == SOCKET_ERROR)
{
return ReceiveStatus::ReceiveSocketError;
}
if(bytesIn > 0)
{
memcpy(packetInternalOut,dataIn,bytesIn);
return ReceiveStatus::ReceiveSuccessful;
}
else
{
return ReceiveStatus::ReceiveEmpty;
}
}
有什么可能影响这是否有效?我的聊天程序可以是服务器,也可以是客户端。他们都使用相同的代码。当等待连接时,服务器会在Select()上停留100秒,因为NETWORKTIMEOUTSEC=100。但在char程序中,每当我想发送消息时,我都会先发送一个传输请求,然后等待确认(对于确认数据包,我需要再次调用receive)。现在这是不等待的步骤。我的ReceiveAck函数调用Receive(),Receive直接运行在整个代码上。我可以通过创建一个客户端而不创建服务器来测试这一点。如果我在没有服务器的地方发送消息,它应该等待100秒才能得到确认,然后超时。但是,我一按回车键,它就说超时了。
我不知道是什么让它跳过这一步。我已经调试了我的聊天程序的服务器和客户端状态。tv和fds的值在两者中是相同的,但服务器会等待,客户端不会。。。
select()
的第一个参数是比最后一个套接字大一个。所以你需要:
n = select ( *p_socket + 1, &fds, NULL, NULL, &tv ) ;
Select在应用程序被信号击中时也会提前返回(即,没有任何具有数据的套接字)。因此,如果你的应用程序在不同的线程中使用了很多usleep()和朋友,你可能会大吃一惊。
select()
应始终用于循环中。您必须检查其退货是否存在三种情况:
-1
(一个错误),您必须对其进行评估以确定它是否致命。EINTR
是一个非致命错误的例子- 零,在这种情况下,一些不确定的时间已经过去,如果你关心它已经过去了多久,你需要单独检查时间
- 正值,在这种情况下,您应该检查所有标记的描述符并对其采取行动
在所有情况下,您都应该检查是否存在任何其他可能使您想要退出循环的条件,例如实际经过了多少时间。
注意,select()
的第一个参数通常应该是常数FD_SETSIZE
。把它设置为其他任何东西都没有什么好处。
还要注意,仅仅因为你收到了一个数据报并不意味着你收到了你想要的数据报。你需要一种方法来检查你是否没有得到一些随机数据报,这些数据报恰好在网络上浮动(它确实发生了)。沿着这些线,确保TOTALPACKETSIZE
是65536,因为这在理论上(大约)是随机数据包的大小
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 如何让LLDB在成功时退出,在失败时等待
- 等待整个 omp 块完成,然后再调用第二个函数
- 提升 ASIO - io_service 不要等待连接到线程
- 如何在C++中实现带有packaged_task的异步等待循环?
- 虚假唤醒是否会解锁所有等待线程,甚至是不相关的线程?
- 如何等待窗口隐藏在Qt中?
- SQLite3 在 c++ 中输出 SELECT 上的空列表
- 如何在不等待检索的情况下获取C++中的内存位置?
- 等待被迷住了,没有回来
- 等待 WaitForMultipleObjects 窗口中的事件数量可变
- 一个线程等待多个线程事件
- 等待 qthread 终止的正确方法是什么?
- 如何在 sys/select.h 中正确使用
- 不可预测的C++睡眠/等待行为
- Bison/flex 在识别规则后等待输入
- select(NULL、NULL、NULL 和超时)是否只是等待给定的时间?
- Select()有时不会等待
- C++select()没有等待超时时间
- 同时等待一个条件(pthread_cond_wait)和一个套接字更改(select)