【问题标题】:Is it possible to have a socket listening to two UDP IPs, one that is 127.0.0.1 (same machine) and a different computer at the same time?是否可以让一个套接字同时监听两个 UDP IP,一个是 127.0.0.1(同一台机器)和另一台计算机?
【发布时间】:2013-11-08 21:20:07
【问题描述】:

我使用的眼动追踪应用程序利用 UDP 发送数据包。我在同一台计算机上制作了一个 python 套接字来监听并将数据转储到 .txt 文件中。我已经有这么多工作了。

另外一个用 python 编写的应用程序(被眼球追踪的对象看到的东西)正在另一台计算机上运行。因为眼动追踪应用程序是连续的并且会发送不必要的数据,所以到目前为止,我不得不手动解析出受试者正在查看所需刺激时的实例。我这样做是基于刺激和眼动追踪应用程序的手动同步启动,然后挖掘日志文件。

我想要做的是让第二台计算机充当第二个 UDP 客户端,每次受试者注视刺激物(其中一个标记插入到 . txt 文件前面提到)。是否可以让一个套接字同时监听两个 IP 地址?

这是我的套接字脚本:

#GT Pocket client program

import datetime
import socket
now = datetime.datetime.now()
filename = 'C:\gazelog_' + now.strftime("%Y_%m_%d_%H_%M") + '.txt'

UDP_IP = '127.0.0.1' # The remote host (in this case our local computer)
UDP_PORT = 6666 # The same port as used by the GT server by default

sock = socket.socket(socket.AF_INET, #internet
                                socket.SOCK_DGRAM) #UDP 

sock.bind( (UDP_IP, UDP_PORT) )

while True:
    data, addr = sock.recvfrom( 1024) #I assume buffer size is 1024 bytes.
    print "Received Message:", data
    with open(filename, "a") as myfile:
    myfile.write(str(data + "\n"))

sock.close()
myfile.close()

编辑:

@abarnert 我能够绑定到以太网接口上的主机地址,并从计算机 B 向计算机 A 发送消息,但计算机 A 不再能够接收来自自身的数据包。当我指定UDP_IP = '0.0.0.0' 时,计算机 B 不再能够通过以太网发送数据。当我指定UDP_IP = '' 时,我收到了`error: [Errno 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted

这与我在计算机 B 上用于发送数据的脚本有关:

import socket

UDP_IP = "169.254.35.231" # this was the host address I was able to send through.
UDP_PORT = 6666
MESSAGE = "Start"

print ("UDP target IP:"), UDP_IP
print ("UDP target port:"), UDP_PORT
print ("message:"), MESSAGE

sock = socket.socket(socket.AF_INET,
                 socket.SOCK_DGRAM) 
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT) )

我不知道我需要在哪里(或根本不知道)我需要指定 INADDR_ANY,所以我没有。但我确实尝试过一次import socket.INADDR_ANY,但得到了ImportError: No module named INADDR_ANY

根据您的回复,这似乎是一个简单的问题,所以我不确定我在哪里搞砸了。

EDIT2:我只是再次重读您的答案并理解为什么 socket.INADDR_ANY 不起作用。请忽略我之前编辑的那部分

EDIT3:好的,我在指定主机 IP 时没有获取数据的原因是我在计算机 A 上收集数据的应用程序仍被指定为发送到 127.0.0.1。所以我想通了。我仍然很好奇为什么 0.0.0.0 不起作用!

【问题讨论】:

  • 你当然可以使用两个socket绑定到你想监听的不同端点
  • 从您的编辑和代码中的 cmets 来看,我认为您仍在混淆远程地址和本地地址的概念。远程地址是您要与之交谈的机器的地址。这是您在客户端中传递给sendto(或connect)的地址。这不能是0.0.0.0。本地地址是您机器的地址。由于您的机器可以有多个地址,因此您必须 bind 其中一个地址才能监听该地址。这是您要使用0.0.0.0 的地方,表示“监听我所有的地址”。

标签: python sockets tcp udp communication


【解决方案1】:

没有。一个套接字一次只能绑定一个地址。*

如果碰巧有一个地址可以同时处理您想要的两件事,您可以使用一个套接字来监听它。在这种情况下,INADDR_ANY 主机 (0.0.0.0) 可能正是您正在寻找的——它将处理所有接口上的任何 (IPv4) 连接,包括环回和其他。即使没有预先存在的地址可以满足您的需求,您也可以通过例如 ipfilter 类型的接口进行设置。

但除此之外,您必须创建两个套接字。这意味着您需要与 select 之类的东西进行多路复用,或者创建两个线程。


在您的情况下,您希望指定一个主机,它可以同时监听本地机器和同一以太网网络上的另一台机器。您可以在以太网接口上获取您的主机地址并绑定它。 (您的机器可以在其任何接口上与自己通信。)通常,在“默认接口”上获取您的地址也适用于此 - 您会在某些地方看到绑定到 socket.gethostname() 的代码,例如 @ 987654321@。但是绑定到INADDR_ANY 要简单得多。除非您想确保某些接口上的机器无法联系到您(例如,如果您正在构建一个打算在防火墙的 DMZ 上运行的服务器,这通常是一个问题),您'通常会想使用INADDR_ANY


最后,如何绑定INADDR_ANY?简短的回答是:只需使用UDP_IP = ''UDP_IP = '0.0.0.0',如果您想更明确的话。任何了解套接字的人,即使他们不了解任何 Python,也会理解 '0.0.0.0' 在服务器代码中的含义。(您可能想知道为什么 Python 在 socket 模块中没有为此提供常量,尤其是即使像 C 这样的低级语言可以。答案是可以,但它并不真正可用。**)


* 请注意,绑定到单个地址并不意味着您只能接收来自单个地址的数据包;这意味着您可以从可以访问该单个地址的所有网络接收数据包。例如,如果你的机器有 LAN 连接,你的地址是 10.0.0.100,和一个 WAN 连接,你的地址是 8.9.10.11,如果你绑定 10.0.0.100,你可以接收来自其他 LAN 客户端的数据包,如 10.0。 0.201 和 10.0.0.202。但是您无法从 9.10.11.12 等 WAN 客户端接收数据包作为 10.0.0.100。

** 在低级套接字 API 中,像 '0.0.0.0' 这样的点字符串地址被转换为像 0 这样的 32 位整数。 Python 有时将这些整数表示为 ints,有时表示为 4 字节缓冲区,如 b'\0\0\0\0'。根据您的平台和版本,socket.INADDR_ANY 常量可以是 0b'\0\0\0\0'bind 方法不会采用0,也可能不会采用b'\0\0\0\0'。如果不先检查您拥有的表单,然后在其上调用正确的函数,您就无法转换为'0.0.0.0'。这很丑陋。这就是为什么使用'0.0.0.0' 会更容易。

【讨论】:

  • 您可能会澄清单个 UDP 套接字可以从任意数量的源接收 UDP 数据包。
  • @JeremyFriesner:我认为这与 OP 的困惑无关;我无法想象在不了解基础知识的情况下谁能做到这一点。但我可能错了……
  • "我想做的是让第二台计算机充当第二个 UDP 客户端,向套接字发送数据包 [...] 是否可以让套接字监听两个 IP一次地址?”
  • @JeremyFriesner:由于 OP 还没有回来,很难说他做了什么,不知道什么。所以假设你可能是对的可能更安全。我会按照你的建议重写答案;谢谢。
  • @JeremyFriesner:当您不确定听众已经知道多少时,很难解释这一点;你能阅读我的编辑并告诉我你认为它是否有效吗?
【解决方案2】:

我相信您可以将原始套接字绑定到整个接口,但您似乎使用了两个不同的接口。

最好使用两个带有 select() 的套接字。

【讨论】:

    猜你喜欢
    • 2013-02-10
    • 1970-01-01
    • 2011-05-20
    • 2012-06-03
    • 2018-08-22
    • 2016-05-25
    • 1970-01-01
    • 1970-01-01
    • 2014-08-24
    相关资源
    最近更新 更多