3

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).

codymanix
  • 28,510
  • 21
  • 92
  • 151

3 Answers3

3

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
  • 62,604
  • 14
  • 116
  • 151
  • 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 May 26 '09 at 16:30
  • 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 May 26 '09 at 21:15
  • are you still facing this problem (the Edit portion of your post) or is it solved by removing connect. – Aditya Sehgal Jul 01 '09 at 16:42
  • 1
    -1: connect is often very useful indeed with UDP. If you don't connect, you won't get back the results of any ICMP replies. If you don't connect and use sendto, your packets go out into the void and you never hear anything back unless the peer happened to get the packet and sent a reply that got through. But, if you connect and there's an IP problem, the OS probably got an ICMP explanation, and will return that to you only of you're connected. – Nicholas Wilson May 31 '13 at 17:16
  • @NicholasWilson connect() is not very useful in a server which wants to serve multiple clients. It's fairly useful in a client app which wants to talk to only one party. – MarkR Jun 03 '13 at 11:23
0

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 Fetissov
  • 82,306
  • 11
  • 110
  • 171
-1

Just a correction in case anyone stumbples across this like I did. To disconnect connect() needs to be called with the sa_family member of sockaddr set to AF_UNSPEC. Not just passed AF_UNSPEC.

badi95
  • 1