views:

716

answers:

2

Iam trying to create an iterative server based on datagram sockets (UDP). It calls connect to the first client which it gets from the first recvfrom() call (yes I know this is no real connect). After having served this client, I disconnect the UDP socket (calling connect with AF_UNSPEC) Then I call recvfrom() to get the first packet from the next client.

Now the problem is, that the call of recvfrom() in the second iteration of the loop is returning 0. My clients never send empty packets, so what could be going on.

This is what Iam doing (pseudocode):

s = socket(PF_INET, SOCK_DGRAM, 0)

bind(s)

for(;;)
{
  recvfrom(s, header, &client_address)  // get first packet from client
  connect(s,client_address)  // connect to this client
  serve_client(s);
  connect(s, AF_UNSPEC); // disconnect, ready to serve next client
}

EDIT: I found the bug in my client accidently sending an empty packet. Now my problem is how to make the client wait to get served instead of sending a request into nowhere (server is connected to another client and doesn't serve any other client yet).

+2  A: 

connect() is really completely unnecessary on SOCK_DGRAM.

Calling connect does not stop you receiving packets from other hosts, nor does it stop you sending them. Just don't bother, it's not really helpful.

CORRECTION: yes, apparently it does stop you receiving packets from other hosts. But doing this in a server is a bit silly because any other clients would be locked out while you were connect()ed to one. Also you'll still need to catch "chaff" which float around. There are probably some race conditions associated with connect() on a DGRAM socket - what happens if you call connect and packets from other hosts are already in the buffer?

Also, 0 is a valid return value from recvfrom(), as empty (no data) packets are valid and can exist (indeed, people often use them). So you can't check whether something has succeeded that way.

In all likelihood, a zero byte packet was in the queue already.

Your protocol should be engineered to minimise the chance of an errant datagram being misinterpreted; for this reason I'd suggest you don't use empty datagrams, and use a magic number instead.

UDP applications MUST be capable of recognising "chaff" packets and dropping them; they will turn up sooner or later.

MarkR
Connect sets an internal filter from which address is received from and send to when using send() or recv().recv(): "For SOCK_DGRAM sockets, data is extracted from the first queued datagram for the destination address specified in the connect call".
codymanix
You are right, my client was sending (due to a bug) an empty packet. Now I have another problem. The client which should be waiting in the queue to get served sends its first request packet (which is never received from the server). Then it tries to receive the response and recv returns -1. How can I make the client wait?
codymanix
are you still facing this problem (the Edit portion of your post) or is it solved by removing connect.
Aditya Sehgal
+1  A: 

man connect:

...
If the initiating socket is not connection-mode, then connect()
shall set the socket’s peer address, and no connection is made.
For SOCK_DGRAM sockets, the peer address identifies where all
datagrams are sent on subsequent send() functions, and limits
the remote sender for subsequent recv() functions. If address
is a null address for the protocol,  the  socket’s  peer  address
shall be reset.
...
Nikolai N Fetissov
So what? In which way does this answer my question?
codymanix
What was the question exactly?
Nikolai N Fetissov
Sorry if I was unclear. The question was why the second call to recvfrom() returns 0. I now found this to be a bug in my code.My problem now is how to make the client wait to get served instead of letting him send data into nowwhere.
codymanix