views:

164

answers:

2

hi

I am facing a problem with socket and I would be glad if you could help ...
The problem is that when I send data more than once it blocks, e.g:

//--- client ---  
//..
send(sock, buf_1, sizeof(buf_1), 0);  

for (x10){   
//...  
send(sock, buf_2, sizeof(buf_2), 0);    
if (recv(sock, buf_2, sizeof(buf_2), 0)<0) printf("recv_2() failed");   
//...   
}  

for (x20){   
//...  
send(sock, buf_3, sizeof(buf_3), 0);     
if (recv(sock, buf_3, sizeof(buf_3), 0)<0) printf("recv_3() failed");   
//...    
}  
//...          

//--- server---   
//...  
if (recv(sock, buf_1, sizeof(buf_1), 0)<0) printf("recv_1() failed"); 

for (x10){     
if (recv(sock, buf_2, sizeof(buf_2), 0)<0) printf("recv_2() failed");    
//...    
send(sock, buf_2, sizeof(buf_2), 0);     
}     

for (x20){   
if (recv(sock, buf_3, sizeof(buf_3), 0)<0) printf("recv_3() failed");   
//...    
send(sock, buf_3, sizeof(buf_3), 0);     
}     
//...   

the exchange blocks just after the first send(), is there any idea?
Does udp support also multiple sendto()?

Thanks for your answer -

+3  A: 

Both send and recv are blocking in this case. You need to set the asynchronous flag ( O_NONBLOCK I think - see docs for fnctl ) on the socket. But this can be tricky to get right. If you dont send/get all the data you have to keep calling send/recv until you've got it all, and doing this efficiently means you're going to have to use the select system call on your sockets.

Now all this is quite feasible, but not much fun and painful to debug. I recommend you try the boost::asio (asynchronous io) library rather than playing with raw sockets. http://www.boost.org/doc/libs/1_41_0/doc/html/boost_asio.html

Michael Anderson
Thanks! the problem is not about asynchronous send/recieve, but it is synchronous
Apollo
+1  A: 

UDP or TCP?

If TCP; how big is the data that you are sending. What is the client doing? Is the client actually receiving and processing the first block of data? What MAY be happening is that the second send call is blocking because your client's receive window is full and the TCP stacks have engaged in flow control which is causing your synchronous send to block pending the peer reading enough data so that the recv window isn't full and the flow control situation has passed...

Note also that if you're dealing with TCP then the recv calls CAN and WILL return any number of bytes between 1 and the number of bytes that you have been sent; you should always loop to accumulate the number of bytes that your message framing tells you that you need...

You mention, at the end of your question, about UDP and multiple sendTos, how does this relate to your question? Are you, in fact, using UDP sockets here?

Len Holgate
Thanks! at this time, I am using TCP and after the first recv it blockes. the server receives just buf_1 and stops whereas the client doesn't do anything. I also envisage to use UDP for this application.
Apollo
Your question is still very vague BUT if the code after the 'server' comment blocks after the first recv (which is what you suggest) then that's completely to be expected because recv will return as many bytes as there are available. As I said in my reply above, you need to manage your recv calls better; your code as it stands is broken in that all the data may be read by the first recv....
Len Holgate
sorry, the question is not vague, but technical ...thanks for your answer anyway ...
Apollo
No, actually, it's vague. For example, you state in your question that "after the first send it blocks" yet you don't say if it's the server code path that blocks, or the client code path that blocks. Your code example also shows some if branches with no context to show which is taken. In your first comment to my reply you state that the server receives just one buf. IMHO, you're not being especially precise (or technical) in the way that you're asking your question. It's not that I don't understand the technical detail, it's just that you're not being especially specific in your questioning.
Len Holgate