Python 使用SO\ U REUSEADDR通过不同的套接字发送和接收数据包

Python 使用SO\ U REUSEADDR通过不同的套接字发送和接收数据包,python,sockets,python-2.7,udp,Python,Sockets,Python 2.7,Udp,作为这个问题的继续: 我尝试过使用SO_REUSEADDR(在意识到我不能使用SO_REUSEPORT之后)。 但是,我的代码仍然不起作用 这是: HOST='127.0.0.1' PORT=10000 recvSock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW) recvSock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sendSo

作为这个问题的继续:

我尝试过使用SO_REUSEADDR(在意识到我不能使用SO_REUSEPORT之后)。 但是,我的代码仍然不起作用

这是:

HOST='127.0.0.1'
PORT=10000
recvSock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
recvSock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

sendSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sendSock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

sendSock.bind((HOST,PORT))
sendSock.sendto("",(HOST,PORT))

recvSock.bind((HOST,PORT))
response,addr = recvSock.recvfrom(65535)
我在第一个“bind”行(binding sendsock)上得到一个错误

如果省略sendSock.bind行,则在recvSock.recvfrom行上会出现错误

由于省略了setsockopt行和bind行,我还得到了一个错误,因此我想我使用setsockopt将两个套接字绑定到同一地址是不好的

在互联网上找不到关于如何使用它们的示例。。。 有什么帮助吗


注:在windows XP上使用python 2.7。

我怀疑这种方法对您不起作用,但我可能错了。我没有可以测试的XP设备,现代Windows以XP没有的方式限制原始套接字。但我会给你更多的信息,试图帮助你解释为什么它不起作用,为什么它可能不起作用,以及你可以尝试什么


但首先,让我解释一下在Windows上执行此操作的正确方法:。像这样:

recvSock.ioctl(socket.SIO_RCVALL, socket.RCVALL_IPLEVEL)
这会告诉Windows将发送给您的计算机的所有IP数据包传送到此套接字。(也可以发送一些发送给其他机器的数据包,但通常不会。如果需要,您需要将NIC置于混杂模式,并启用
RCVALL_

请注意,“所有数据包”指的是你不关心的大量数据包,因此你需要对它们进行过滤。换句话说,你需要不断地阅读数据包,检查它们的本地地址,跳过它们,直到找到你想要的数据包,而不是只读取一个数据包

使用
SIO_RCVALL
时,不要试图将套接字绑定到特定的主机和端口。要让它正常工作,有很多问题,在Windows上会随着版本的变化而变化,这是不值得的。Windows仍然会提供至少一些用于其他端口的数据包,所以您仍然需要对它们进行过滤


或者,您可以使用with,这使您可以轻松设置数据包捕获,使用您想要的任何选项,在您想要的任何接口上,使用自定义过滤器,并轻松接收您想要的数据包


使事情变得更容易,尽管在Windows上启动并运行
scapy
可能不像尝试项目那样容易,而不是自己动手


现在,你错在这里了


我不确定为什么在
sendSock.bind
调用中出现错误,但可能是因为10000超出了临时端口范围。在XP上,默认范围为1025-5000。有关详细信息,请参阅MSDN文档。但是,如果您不关心源端口是什么,您可以始终只
sendto
,而不使用
bind
,然后使用找出最终使用的端口,然后使用该端口绑定另一个套接字。但是,如果不选择端口,则可能无法选择主机。(这取决于平台,但我很确定在Windows XP上,您只能使用非
INADDR\u ANY
主机和端口
0
来实现TCP,而不是UDP。)


在Windows上,如果两个活动套接字都绑定到同一地址(直接或间接,例如,通过一个绑定到
0.0.0:10000
,另一个绑定到
192.168.1.123:10000
),内核将包任意且不确定地传递到两个套接字中的一个。有关更多详细信息,请参阅MSDN文章。不管那些文档怎么说,这对于原始套接字来说并不完全正确。但是,至少在某些Windows版本上,这在一定程度上是正确的


协议为
IPPROTO_raw
的Windows原始套接字将不会接收任何内容。如果协议匹配,Windows仅将数据包传送到原始套接字,因此
IPPROTO_UDP
数据包不会传送到
IPPROTO_原始
套接字。但这个问题很容易解决,只需使用
IPPROTO_UDP
。见MSDN;发送和接收操作部分解释了如何传递数据包

此外,如果绑定本地端,则可能需要绑定原始套接字的远程端。您可以使用UDP套接字上用于发送的相同地址调用
connect
。这在早期的WinSock2中不是必需的,但在以后的XP service Pack中可能会用到(至少在默认设置下)



这也可能受到内置Windows防火墙是否启用的影响(以不可预测的方式)。关闭它以避免出现这种情况。

您收到了什么错误?您不应该在
sendSock.bind
行中收到错误。同时,如果您不关心所使用的源端口,您可以通过使用
sendto
,获得任意临时端口,然后调用
sendSock.getsockname()
,找出它得到的端口,并在绑定
recvSock
中使用它。然而,出于多种原因,这对你没有任何帮助。让我解释一下。另外,请给出完整的平台。XPSP1和XPSP3都改变了原始套接字的行为,所以仅仅说“XP”是不够的。(完整的Python版本信息也很有用,例如,“来自Python.org二进制安装程序的32位2.7.3”。)