[英]How to set time out for receiving message fromt client of server with non-blocking mode?
I have a server
with 2 connections SOCKET
which is connected with clients
and I set this server
is non-blocking mode which don't stop when sending or recieving message. 我有一个具有2个连接
SOCKET
的server
,该server
与clients
连接,并且我将此server
设置为非阻止模式,该模式在发送或接收消息时不会停止。 I want to set time out for a SOCKET
of each connections, but if I use the following code: 我想为每个连接的
SOCKET
设置超时,但是如果使用以下代码:
void getMessage(SOCKET connectedSocket, int time){
string error = R_ERROR;
// Using select in winsock
fd_set set;
timeval tm;
FD_ZERO(&set);
FD_SET(connectedSocket, &set);
tm.tv_sec = time; // time
tm.tv_usec = 0; // 0 millis
switch (select(connectedSocket, &set, 0, 0, &tm))
{
case 0:
// timeout
this->disconnect();
break;
case 1:
// Can recieve some data here
return this->recvMessage();
break;
default:
// error - handle appropriately.
break;
}
return error;
}
My server is not none-blocking mode any more! 我的服务器不再是无阻塞模式! I have to wait until the end of 1st connection's time out to get message from the 2nd connection!
我必须等到第一个连接的超时结束才能从第二个连接获取消息! That's not what I expect!
那不是我所期望的! So, is there any way to set time out for non-blocking mode?
那么,有什么办法可以为非阻塞模式设置超时时间? Or I have to handle it myself?
还是我必须自己处理?
select
is a demultiplexing mechanism. select
是一种解复用机制。 While you are using it to determine when data is ready on a single socket or timeout, it was actually designed to return data ready status on many sockets (hence the fd_set
). 当您使用它来确定单个套接字上的数据何时准备就绪或超时时,它实际上是为在许多套接字上返回数据就绪状态而设计的(因此
fd_set
)。 Conceptually, it is the same with poll
, epoll
and kqueue
. 从概念上讲,
poll
, epoll
和kqueue
。 Combined with non-blocking I/O, these mechanisms provide an application writer with the tools to implement a single threaded concurrent server. 这些机制与非阻塞I / O相结合,为应用程序编写者提供了用于实现单线程并发服务器的工具。
In my opinion, your application does not need that kind of power. 我认为,您的应用程序不需要那种功能。 Your application will only be handling two connections, and you are already using one thread per connection.
您的应用程序将仅处理两个连接,并且每个连接已使用一个线程。 I believe leaving the socket in blocking I/O mode is more appropriate.
我相信让套接字处于阻塞I / O模式更为合适。
If you insist on non-blocking mode, my suggestion is to replace the select
call with something else. 如果您坚持使用非阻塞模式,我的建议是将
select
调用替换为其他内容。 Since what you want from select
is an indication of read readiness or timeout for a single socket, you can achieve a similar effect with recv
passed with appropriate parameters and with the appropriate timeout set on the socket. 由于您要从
select
中获得的信息是单个套接字已准备就绪或超时的指示,因此通过在适当的参数上设置套接字并设置适当的超时,可以通过recv
达到类似的效果。
tm.tv_sec = time;
tm.tv_usec = 0;
setsockopt(connectedSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tm, sizeof(tm));
char c;
swtich (recv(connectedSocket, &c, 1, MSG_PEEK|MSG_WAITALL)) {
case -1:
if (errno == EAGAIN) {
// handle timeout ...
} else {
// handle other error ...
}
break;
case 0: // FALLTHROUGH
default:
// handle read ready ...
break;
}
From man recv
: 从
man recv
:
MSG_PEEK -- This flag causes the receive operation to return data from the beginning of the receive queue without removing that data from the queue.
MSG_PEEK-此标志使接收操作从接收队列的开头返回数据,而不从队列中删除该数据。 Thus, a subsequent receive call will return the same data.
因此,后续的接收呼叫将返回相同的数据。
MSG_WAITALL (since Linux 2.2) -- This flag requests that the operation block until the full request is satisfied.
MSG_WAITALL(从Linux 2.2开始)-此标志请求操作块,直到满足完整请求为止。 However, the call may still return less data than requested if a signal is caught, an error or disconnect occurs, or the next data to be received is of a different type than that returned.
但是,如果捕获到信号,发生错误或断开连接,或者下一个要接收的数据与返回的数据类型不同,则呼叫返回的数据仍可能比请求的少。
As to why select
is behaving in the way you observed. 至于为什么
select
以您观察的方式表现。 While the select
call is thread-safe, it is likely fully guarded against reentrancy. 尽管
select
调用是线程安全的,但可能会完全防止重入。 So, one thread's call to select
will only come in after another thread's call completes (the calls to select
are serialized). 因此,一个线程的
select
调用只会在另一个线程的调用完成之后才进行( select
的调用已序列化)。 This is inline with its function as a demultiplexer. 这与其作为解复用器的功能是一致的。 It's purpose is to serve as a single arbiter for which connections are ready.
目的是充当准备好连接的单个仲裁器。 As such, it wants to be controlled by a single thread.
因此,它希望由单个线程控制。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.