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. I want to set time out for a SOCKET
of each connections, but if I use the following code:
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. 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 thefd_set
). Conceptually, it is the same withpoll
,epoll
andkqueue
. Combined with non-blocking I/O, these mechanisms provide an application writer with the tools to implement a single threaded concurrent server.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.
If you insist on non-blocking mode, my suggestion is to replace the
select
call with something else. Since what you want fromselect
is an indication of read readiness or timeout for a single socket, you can achieve a similar effect withrecv
passed with appropriate parameters and with the appropriate timeout set on the socket.From
man recv
:As to why
select
is behaving in the way you observed. While theselect
call is thread-safe, it is likely fully guarded against reentrancy. So, one thread's call toselect
will only come in after another thread's call completes (the calls toselect
are serialized). 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.