在 Linux 上使用连接功能时,UDP 套接字无法接收回复

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

我使用 Python 编写了一个 udp 服务器和客户端。代码很简单。当udp客户端向服务器端发送数据时,服务器端回复一条消息给客户端。

服务器代码如下,文件名是"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()

客户端代码如下,文件名是"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()

客户端收不到任何回复。但是,如果我评论以下内容 客户端代码中的 connect 行,它工作正常。

#s.connect(addr)

由于相同的客户端代码在具有 connect 行的另一台 Linux 机器上运行良好,所以我想知道我的 Linux 有什么问题机器?是否有任何 Linux 内核限制或 TCP/UDP 套接字限制?

希望得到您的解答,谢谢!

您的代码中有一个假设可能不正确。通过将 10.0.0.12 传递给 connect,您将客户端配置为仅接受源 IP 地址为 10.0.0.12 的传入数据报。但是您的服务器中没有任何东西可以确保源 IP 地址是 10.0.0.12 或者源 IP 地址将匹配相应查询的目标地址。

考虑:

  1. 客户端连接到 10.0.0.12:19998
  2. 客户端以其 IP 地址之一作为源地址向 10.0.0.12:19998 发送数据报。
  3. 服务器收到发送到 10.0.0.12:19998 的查询。
  4. 服务器对该数据报的源 IP 地址形成响应并发送它。
  5. 服务器选择了 10.0.0.12 以外的一些源 IP 地址,因为它似乎 "closer" 到目的地。服务器的 IP 堆栈不知道此数据报在任何意义上都是对接收到的数据报的答复,因此没有理由将源 IP 地址设置为 10.0.0.12。
  6. 客户端拒绝回复,因为它连接到 10.0.0.12 而回复来自其他 IP 地址。

解决方案的简短版本是不对 UDP 使用 connect 除非服务器保证总是发送一个源 IP 地址与客户端要发送的 IP 地址相匹配的回复数据报 connect 到。您的设置中没有任何内容可以保证这一点。

通常的解决方案是永远不要将 UDP 套接字绑定到通配符 IP 地址。相反,将套接字绑定到服务器将用于与其客户端通信的特定 IP 地址。