Search code examples
pythonsockets

python socket recv timeout while Wireshark shows received UDP packet (windows)


I have the following diagram:

Send: client --(tx_socket)--> server

Reply: server -- (rx_socket) --> client

def connect(self) -> None:
    self.tx_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    self.tx_socket.bind(("", self.tx_src_port))

    self.rx_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    self.rx_socket.settimeout(3.0)
    self.rx_socket.bind(("", self.rx_dst_port))

However, I always get timeout error when waiting for reply from server, even when Wireshark shows the reply packet:

self.tx_socket.sendto(command_str, (self.dst_addr, self.tx_dst_port))
self.rx_socket.recv(4096) # <--- TimeoutError

Somehow, this can be solved by sending a character from client to server using rx_socket in advance:

self.rx_socket.sendto("\n".encode('ascii'), (self.dst_addr, self.tx_dst_port))

But I do not understand why this happens. Also, the same issue does not exist in Linux.

Can you give me an explaination ? Any reply is greatly appreciated.


Solution

  • TL;DR: don't use different ports/sockets for sending and receiving.

    Sending from one port but receiving on another will cause trouble with stateful firewalls, network address translation etc. The transmitted packet will create a state in the middlebox (firewall, router) and to match this state any reply packet needs to be targeted at the original sender, i.e. same IP and port. Any other packets will not match any existing state and will thus be discarded by the middlebox, resulting in the packet loss and the timeout you experience.