从Python脚本

时间:2017-09-18 06:18:38

标签: python multithreading sockets

我正在尝试让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()

每个听众都需要对收到的数据进行一些特定的处理(在两种情况下不同),因此将两者分开对我来说是可以的。

再次感谢大家!

1 个答案:

答案 0 :(得分:0)

您可以使用select-Module一次等待多个非阻塞套接字上的数据。

另一种可能性是每个套接字使用单独的线程并继续使用阻塞套接字,但是你必须同步你的线程。

这取决于代码的一般结构,哪种方式更容易或更好。

编辑:

从非阻塞套接字收到当前没有数据时,抛出BlockingIOError 10035,这意味着“如果这不是非阻塞套接字,则此操作将被阻止”。

在更改后的代码中,您可能无法读取for循环中的所有套接字,但只能从那些已准备好返回的套接字中读取。您可能想要阅读阻塞/非阻塞套接字的基础知识,例如在Beej's Guide中。