The UDP socket cannot receive replies when connect function is used on Linux

566 views Asked by At

I write a udp server and client using Python. The code is simple. When the udp client sends data to the server, the server replies a message to the client.

The server code is as follows, the filename is "serverudp.py".

#!/usr/bin/env python

from socket import *
HOST = ''
PORT = 19998
s = socket(AF_INET,SOCK_DGRAM)
s.bind((HOST,PORT))
print '...waiting for message..'
while True:
    data,address = s.recvfrom(1024)
    print data,address
    s.sendto('this is the UDP server',address)
s.close()

The client code is as follows, the filename is "clientudp.py"

#!/usr/bin/env python
from socket import *
HOST='10.0.0.12'
PORT=19998
addr=(HOST,PORT)
s = socket(AF_INET,SOCK_DGRAM)
s.connect(addr)
while True:
    message = raw_input('send message:>>')
    s.sendto(message, addr)
    data = s.recv(1024)
    print data
s.close()

The client can not receive the any reply. However, if I comment the following connect line in the client code, it works correctly.

#s.connect(addr)

As the same client code works well on another Linux machine with the connect line, so I want to know what's the problem with my Linux machine? Is there any Linux kernel restriction or TCP/UDP socket restriction with it?

I hope your answers, thank you!

1

There are 1 answers

3
David Schwartz On BEST ANSWER

You have an assumption in your code that may be incorrect. By passing 10.0.0.12 to connect, you are configuring your client to only accept incoming datagrams with a source IP address of 10.0.0.12. But nothing in your server either ensures that the source IP address is 10.0.0.12 or that the source IP address will match the destination address of the corresponding query.

Consider:

  1. Client connects to 10.0.0.12:19998
  2. Client sends datagram to 10.0.0.12:19998 with one of its IP addresses as the source address.
  3. Server receives query sent to 10.0.0.12:19998.
  4. Server forms response to the source IP address of that datagram and goes to send it.
  5. Server chooses some source IP address other than 10.0.0.12 because it seems "closer" to the destination. The server's IP stack has no idea this datagram is in any sense a reply to the received datagram and so has no reason to set the source IP address to 10.0.0.12.
  6. Client rejects the reply because it is connected to 10.0.0.12 and the reply is from some other IP address.

The short version of the solution is not to use connect for UDP unless the server is guaranteed to always send a reply datagram with a source IP address that matches the IP address the client is going to connect to. Nothing in your setup assures this.

The usual solution is to never bind a UDP socket to a wildcard IP address. Instead, bind the socket to the specific IP address the server is going to use to communicate with its clients.