Python套接字接收/发送多线程
我正在编写一个Python程序,在主线程中,我使用recv函数通过TCP套接字连续(在循环中)接收数据。在回调函数中,我使用sendall函数通过同一套接字发送数据。触发回调的因素无关紧要。我已将套接字设置为阻塞Python套接字接收/发送多线程,python,multithreading,sockets,thread-safety,Python,Multithreading,Sockets,Thread Safety,我正在编写一个Python程序,在主线程中,我使用recv函数通过TCP套接字连续(在循环中)接收数据。在回调函数中,我使用sendall函数通过同一套接字发送数据。触发回调的因素无关紧要。我已将套接字设置为阻塞 我的问题是,这样做安全吗?我的理解是,回调函数是在单独的线程(而不是主线程)上调用的。Python套接字对象是线程安全的吗?从我的研究中,我得到了相互矛盾的答案。Python中的套接字不是线程安全的 您试图同时解决几个问题: 套接字不是线程安全的 recv正在阻塞并阻塞主线程 正在从其
我的问题是,这样做安全吗?我的理解是,回调函数是在单独的线程(而不是主线程)上调用的。Python套接字对象是线程安全的吗?从我的研究中,我得到了相互矛盾的答案。Python中的套接字不是线程安全的 您试图同时解决几个问题:
select.select
和socketpair
,并使用队列处理传入数据
import select
import socket
import queue
# Any data received by this queue will be sent
send_queue = queue.Queue()
# Any data sent to ssock shows up on rsock
rsock, ssock = socket.socketpair()
main_socket = socket.socket()
# Create the connection with main_socket, fill this up with your code
# Your callback thread
def different_thread():
# Put the data to send inside the queue
send_queue.put(data)
# Trigger the main thread by sending data to ssock which goes to rsock
ssock.send(b"\x00")
# Run the callback thread
while True:
# When either main_socket has data or rsock has data, select.select will return
rlist, _, _ = select.select([main_socket, rsock], [], [])
for ready_socket in rlist:
if ready_socket is main_socket:
data = main_socket.recv(1024)
# Do stuff with data, fill this up with your code
else:
# Ready_socket is rsock
rsock.recv(1) # Dump the ready mark
# Send the data.
main_socket.sendall(send_queue.get())
我们在这里使用多个构造。您必须用您选择的代码填充空格。关于解释:
我们首先创建一个send\u队列
,它是一个要发送的数据队列。然后,我们创建一对连接的套接字(socketpair()
)。稍后我们需要它来唤醒主线程,因为我们不希望recv()
阻塞和阻止对套接字的写入
然后,我们连接main_套接字
,并启动回调线程。现在,这里是魔术:
在主线程中,我们使用select.select
来了解rsock
或main\u socket
是否有任何数据。如果其中一个有数据,主线程将被唤醒
向队列添加数据后,我们通过发出信号ssock
唤醒主线程,该信号唤醒rsock
,从而从select.select>返回
为了完全理解这一点,您必须阅读,并且。这里有一些隐藏的问题,您正试图立即解决。希望我给了你一个详细的答案,但是可以自由地问你是否理解。考虑使用异步I/O来处理你的用例,那么你就不需要线程了。我实际上在使用MyPython,它看起来像MyPython不支持Socket。这有什么关系吗?也许创建一个类似的函数,或者只是创建两个附加的套接字?谢谢@Alonsocketpair
的操作与在本地主机上创建2个套接字几乎相同。您可以创建2个套接字,也可以设置一个较低的select。选择timeout并轮询。我显然不喜欢轮询选项,因为它浪费资源,速度较慢,如果您已经在运行MicroPython,我想您这样做是有原因的,轮询会很糟糕。选择两个额外的套接字。@请记住,在unix上选择。选择也适用于任何其他文件描述符,而不仅仅是套接字。如果fd对您有任何帮助,您可以使用不同的fd,但我不认为这样做有什么好处(我想管道会更高效一些,但不值得为此破坏交叉兼容性)。如果我需要创建两个额外的套接字(总共三个),只创建两个TCP套接字连接是否更好,一个用于输入,一个用于输出?它需要更少的一个套接字,并且可能更容易编码。选择器
模块更好