在 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 地址将匹配相应查询的目标地址。
考虑:
- 客户端连接到 10.0.0.12:19998
- 客户端以其 IP 地址之一作为源地址向 10.0.0.12:19998 发送数据报。
- 服务器收到发送到 10.0.0.12:19998 的查询。
- 服务器对该数据报的源 IP 地址形成响应并发送它。
- 服务器选择了 10.0.0.12 以外的一些源 IP 地址,因为它似乎 "closer" 到目的地。服务器的 IP 堆栈不知道此数据报在任何意义上都是对接收到的数据报的答复,因此没有理由将源 IP 地址设置为 10.0.0.12。
- 客户端拒绝回复,因为它连接到
10.0.0.12
而回复来自其他 IP 地址。
解决方案的简短版本是不对 UDP 使用 connect
除非服务器保证总是发送一个源 IP 地址与客户端要发送的 IP 地址相匹配的回复数据报 connect
到。您的设置中没有任何内容可以保证这一点。
通常的解决方案是永远不要将 UDP 套接字绑定到通配符 IP 地址。相反,将套接字绑定到服务器将用于与其客户端通信的特定 IP 地址。
我使用 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 地址将匹配相应查询的目标地址。
考虑:
- 客户端连接到 10.0.0.12:19998
- 客户端以其 IP 地址之一作为源地址向 10.0.0.12:19998 发送数据报。
- 服务器收到发送到 10.0.0.12:19998 的查询。
- 服务器对该数据报的源 IP 地址形成响应并发送它。
- 服务器选择了 10.0.0.12 以外的一些源 IP 地址,因为它似乎 "closer" 到目的地。服务器的 IP 堆栈不知道此数据报在任何意义上都是对接收到的数据报的答复,因此没有理由将源 IP 地址设置为 10.0.0.12。
- 客户端拒绝回复,因为它连接到
10.0.0.12
而回复来自其他 IP 地址。
解决方案的简短版本是不对 UDP 使用 connect
除非服务器保证总是发送一个源 IP 地址与客户端要发送的 IP 地址相匹配的回复数据报 connect
到。您的设置中没有任何内容可以保证这一点。
通常的解决方案是永远不要将 UDP 套接字绑定到通配符 IP 地址。相反,将套接字绑定到服务器将用于与其客户端通信的特定 IP 地址。