Click to See Complete Forum and Search --> : blocking vs. non-blocking sockets / select


fritz_egner
January 1st, 2005, 02:33 AM
Hi there!

I spent the whole day by reading about "blocking, non-blocking sockets" articles, but get more confused the more I read. Some people say, that you should avoid non-blocking sockets, some say there are very powerful. But I do not know which i should use with my project. With both I run into problems.

My project:
I send a ping request to my robots. The robots in the network responds and I create for each robot that replies a thread(max. 16). In each thread I create a socket and it connects to one client(robot). Now, I want to receive messages from the robots. If there is no message send from the robot, I check if I want to send a keystroke to the robot.

Here the code:


void threadFunction(void* p){

Robot* localRobo = p;

//main loop
while(localRobo->exists)
{
//recv data
if(recvFromClient() > 0)
{
..do something with the received data
}

//send keystroke
if(localRobo->KEY_Read()) //reads keystroke (non-blocking)
{
..send keystroke to robot
}

}
}


int recvFromClient()
{
int received = 0;
FD_SET fdSet_read;
timeval timeout;

timeout.tv_sec=1; //wait for 1 sec
timeout.tv_usec=0;

FD_ZERO(&fdSet_read);
FD_SET(connectedSocket, &fdSet_read);

select(0,&fdSet_read,NULL,NULL,&timeout);

if(FD_ISSET(connectedSocket, &fdSet_read))
{

received=recv(connectedSocket,(char*)&buffer[received].....);
.....

}

return received;
}


If I use blocking sockets, the thread stops at the recv() function until the robot sends something. But then I am not able to send my keystroke at any time.
If I use non-blocking sockets, it works fine but my CPU is on 100% :-(

I tried it with the select() function (also in blocking, non-blocking and with timeout).
If the select() is in blocking mode, i cannot send my keystroke at any time.
If it is in non-blocking mode -> 100%CPU
If it is in timeout (i.e. 1s), everything works and CPU is around 7%. But i guess this is still "polling"
As far as I know there a two methods for non-blocking sockets, "polling" and
"asynchron notification". I guess "polling" causes the high CPU load. What about asynchron notification? My program is not a Win32 program so I cannot use WSAAsyncSelect. Is there another way to use that? I thought it would be the select() function. But with select i run into the mentioned problems.

Is there a better way to implement that. Is the idea of one thread for each robot ok?
I was thinking of creating two threads for each robot. One thread that recvs the data. Than it can be in blocking mode and the CPU is happy. And the other thread is for sending the keystrokes to the robot.
What do you think would be the best solution for that.

Cheers,
Fritz

j0nas
January 2nd, 2005, 06:55 PM
As you already know, select() can be used in three ways:
1. Polling (timeout=0)
2. With timeout
3. and without timeout (waits until something happens)

The third alternativ is of course the best.

If I understand you correctly, you want to either recv from robot or local (host) keyboard (which ever comes frist)?! select() would have worked great if your program only would be running a Unix system, but unfortunately Windows doesn't let you to do select() on STDIN :-(

You say that your program is not a Win32 program... if you don't care about a Windows port and your system is Unix-based, you can really do a select() on STDIN. That would solve your issue quite nicely.

Mathew Joy
January 5th, 2005, 03:23 AM
There is nothing like 'non-blocking sockets are powerful than blocking socket' or vice versa. It is the IO method that makes it powerful or powerless. In win32 there are a veriety of IO methods to choose from; most non-win32 platform do not have that luxury. But polling is bad, esp tight ones. Select is not very good either, but for small(with regard to the networking side) applications, it is OK.

In my opinion, one thread per client, is enough in your case. If the number of clients is not high at a given time(as I understand, 16 in your case), this modal is OK. Re-structure you thread proc in a way that it follows sequential events. You can create the threads before hand if you know the total no of clients that will be connected at a given time, thereby avoiding the overhead of creating and killing the threads dynamically. Of-course the best design depends on the particular application, but the suggestions can be taken in general.

PS: It is also possible to time out recv using the SO_RCVTIMEO socket option.