我正在尝试让Python脚本使用两个不同的UDP套接字(一个套接字,一个端口)从两个不同的端口接收数据,初始化如下:
# socket 1
source1_UDPSock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
source1_UDPSock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
source1_port = 6008
source1_listen_addr = ("",source1_port)
source1_UDPSock.bind(source1_listen_addr)
# socket 2
source2_DPSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
source2_UDPSock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
source2_port = 6009
source2_listen_addr = ("", source2_port)
source2_UDPSock.bind(source2_listen_addr)
当我需要使用以下行检索收到的数据时出现问题:
soc1_data, addr = source1_UDPSock.recvfrom(source1_port)
soc2_data, addr = source2_UDPSock.recvfrom(source2_port)
代码运行正常,但是如果我没有从第一个 recvfrom 获取任何数据,它将阻止执行,直到它获得某些东西。我尝试在两个套接字中使用 source1_UDPSock.setblocking(False)将两个套接字设置为非阻塞,但它显示为一个糟糕的解决方案,因为我必须等待一到两秒才能阻止阻塞:出现[WinError 10035],丢失可能正从其他端口接收的数据。
在将两个端口设置为非阻塞后,我尝试在以下代码中使用选择:
ready_read, ready_write, exceptional = select.select([source1_UDPSock, source2_UDPSock], [],[], None)
for ready in ready_read:
data_1, addr = source1_UDPSock.recvfrom(source1_port)
data_2, addr = source2_UDPSock.recvfrom(source2_port)
但我没有成功,因为它继续抛出BlockingIOError 10035。
使用多线程(一个线程,一个开放套接字)可以解决这个问题吗?
提前谢谢你。
问题解决了!
最后,我应用了此question中的解决方案,执行了一些调整。我将端口侦听器分成两个文件并创建了这个脚本:
import multiprocessing
import subprocess
def worker(file):
subprocess.Popen(['python', file])
if __name__ == "__main__":
files = ['listener1.py', 'listener2.py']
for i in files:
p = multiprocessing.Process(target = worker(i))
p.start()
每个听众都需要对收到的数据进行一些特定的处理(在两种情况下不同),因此将两者分开对我来说是可以的。
再次感谢大家!
答案 0 :(得分:0)
您可以使用select-Module一次等待多个非阻塞套接字上的数据。
另一种可能性是每个套接字使用单独的线程并继续使用阻塞套接字,但是你必须同步你的线程。
这取决于代码的一般结构,哪种方式更容易或更好。
编辑:
从非阻塞套接字收到当前没有数据时,抛出BlockingIOError 10035,这意味着“如果这不是非阻塞套接字,则此操作将被阻止”。
在更改后的代码中,您可能无法读取for循环中的所有套接字,但只能从那些已准备好返回的套接字中读取。您可能想要阅读阻塞/非阻塞套接字的基础知识,例如在Beej's Guide中。