是否可以让套接字监听两个UDP IP,一个127.0.0.1(同一台机器)和另一台计算机同时?

时间:2013-11-08 21:20:07

标签: python sockets tcp udp communication

我使用的眼动追踪应用程序利用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不起作用!

2 个答案:

答案 0 :(得分:1)

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

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

但是否则,你必须创建两个套接字。这意味着您需要复用select之类的东西,或者创建两个线程。


在您的情况下,您希望指定可以同时侦听本地计算机和同一以太网网络上的另一台计算机的主机。您可以在以太网接口上获取您的主机地址并绑定它。 (你的机器可以在任何接口上与自己交谈。)通常,在“任何接口是默认接口”上获取你的地址也适用于此 - 你会看到在某些地方绑定到socket.gethostname()的代码,比如Python Socket Programming HOWTO。但绑定到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作为10.0.0.100接收来自WAN客户端的数据包。

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

答案 1 :(得分:0)

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

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