Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 是否可以通过不同的套接字发送和接收数据包?_Python_Sockets_Udp_Client Server_Raw Sockets - Fatal编程技术网

Python 是否可以通过不同的套接字发送和接收数据包?

Python 是否可以通过不同的套接字发送和接收数据包?,python,sockets,udp,client-server,raw-sockets,Python,Sockets,Udp,Client Server,Raw Sockets,我在谷歌上搜索了一会儿,在这里阅读了有关通过套接字发送和接收的相关问题,但找不到我的问题的答案: 我可以通过不同的套接字发送和接收数据包吗 我想实现如下内容: HOST='127.0.0.1' PORT=10000 recvSock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW) sendSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sen

我在谷歌上搜索了一会儿,在这里阅读了有关通过套接字发送和接收的相关问题,但找不到我的问题的答案:

我可以通过不同的套接字发送和接收数据包吗

我想实现如下内容:

HOST='127.0.0.1'
PORT=10000
recvSock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
sendSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

sendSock.sendto("",(HOST,PORT))
response,addr = recvSock.recvfrom(65535)
基本上,我希望通过sendSock(UDP套接字)向echo服务器发送消息,并通过recvSock(原始套接字)从服务器接收答案


可能吗?如果是的话,怎么办?关于的代码不起作用。

让我们后退一点,因为你的问题写得没有多大意义,但我想我知道你想做什么

当您创建一个UDP套接字并在其上发送消息时,这做了两件事:首先,它从临时范围中选择一个适当的源地址(带有任意端口),并将套接字绑定到该地址。(UDP地址是主机IP和端口。)然后它将消息从源地址发送到目标地址

当远程端响应时,它将向该源地址发送消息。内核接收到该消息并看到它指向UDP套接字绑定到的地址。因此,它将消息传递到该套接字

这意味着
recvfrom
只能在该套接字上工作,而不能在另一个套接字上工作。仅在不绑定任何内容的不同套接字上调用
recvfrom
,不会有任何好处

如果可以将两个套接字绑定到同一个地址会怎么样?您可以使用套接字选项
SO\u REUSEADDR
和/或
SO\u REUSEPORT
。有关每个选项何时允许的一些(高度平台特定的)详细信息,请参阅。但是,即使在允许的情况下,当接收到一个绑定了两个套接字的地址的消息时会发生什么?嗯,这也是高度特定于平台的。理论上,消息被任意地传递到其中一个套接字。实际上,在某些平台上,内核将记住谁最近发送到响应的源地址,或发送到与源地址相同的网络上的任何地址,或谁最近绑定,或其他一些规则,并发送到该地址。因此,根据您的平台,这可能对您有帮助,也可能对您没有帮助。您可以
绑定
一个套接字,使用它来
发送到
,然后
绑定第二个套接字,然后在第二个套接字上
接收
,并获得响应。也可能不是。如果它做不到你想要的,不要试图与你的内核抗争;如果你想躲起来,还有更好的办法

如果您绑定到一个更具包容性的地址怎么办?例如,您可以将第一个套接字绑定到
('127.0.0.1',12345)
,然后将第二个套接字绑定到
('0.0.0',12345)
,这些是不同的地址,对吗?基本上,这与将它们绑定到同一个套接字类似。平台特定的差异在我上面链接的同一个答案中解释,如果允许这样做,行为将与使用同一地址相同。在大多数平台上,即使您将(原始)套接字绑定到接口而不是地址,也是如此

除此之外,经典的BSD原始套接字甚至不能接收UDP(或TCP)数据包。除非您构建一个包过滤器来重新路由它们,否则它们总是由内核处理并发送到UDP或TCP套接字(如果没有,则发送到防火墙)。根据最初定义的BSD原始套接字协议,准确地解释了可以接收和不能接收的内容。幸运的是,大多数现代平台都超越了最初的BSD套接字协议。不幸的是,它们都以不同的方式实现

您可以通过将套接字置于混杂模式来解决这两个问题,这意味着它将在路由之前获取其接口上的所有数据包。(在每个平台上执行此操作的方式也不同。)然后由您确定哪些将被路由到您的UDP套接字并进行适当的处理。(对于UDP来说,这并不难;对于TCP来说,这会变得更复杂,因为TCP数据包在传输到套接字之前会被存储并按顺序放回。)

更简单的解决方案是使用平台的数据包过滤器接口

或者,更简单的方法是使用像
libpcap
这样的东西,它具有跨平台的包捕获包装器

或者,更简单的方法是使用
scapy
,它在
libpcap
周围有Python包装,以及其他所有必要的东西,或者使用
wireshark
,这是一个可以从Python自动执行的独立程序。这样做可以准确地捕获将要传递到套接字的数据包,并解析头文件和您想要执行的所有其他操作


或者,一些平台提供了一种获取UDP套接字上所有数据包的报头的方法。这需要使用
recvmsg
而不是
recvfrom
,因为报头是作为“辅助数据”而不是作为主接收缓冲区的一部分传递的。Python3.3有
recvmsg
;早期版本没有,您必须使用
ctypes
或某些第三方包装(或构建您自己的包装)。

当然,但您需要对UDP进行解码/编码protocol@Torxed:“当然”?
recvSock
无法接收作为对其
sendSock.sendto的响应发送的数据。同时,在你的最后一个问题上,我说如果你想让任何人帮你做类似的事情,你必须给出你的平台和版本。今天仍然如此。对于任何这样的问题,任何非特定于平台的答案都是有限的;任何人都可以说“一些平台可以做X,但它们以不同的方式做,而另一些平台不能做X,但可以做Y,这可能是你所需要的,也可能不是你所需要的,而另一些平台不能做任何类似的事,而且它们中的大多数多年来都发生了变化”,