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

时间:2019-01-19 09:20:56

标签: linux sockets udp

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

服务器代码如下,文件名是“ serverudp.py”。

OPENIMAGEIO_LIBRARY_DIRS

客户端代码如下,文件名为“ clientudp.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()

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

#!/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 行的另一台Linux机器上可以很好地工作,所以我想知道我的Linux机器出了什么问题?是否有Linux内核限制或TCP / UDP套接字限制?

希望你的回答,谢谢!

1 个答案:

答案 0 :(得分:1)

您的代码中有一个假设可能不正确。通过将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地址,因为它似乎离目标“更近”。服务器的IP堆栈不知道此数据报在任何意义上都是对接收到的数据报的答复,因此没有理由将源IP地址设置为10.0.0.12。
  6. 客户端拒绝答复,因为它已连接到10.0.0.12,并且答复来自其他IP地址。

该解决方案的简短版本是不对UDP使用connect,除非保证服务器始终发送答复数据报,该答复数据报的源IP地址与客户端要访问的IP地址{{1} } 至。您的设置中没有任何东西可以保证这一点。

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