Python Socket接收/发送多线程
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python Socket接收/发送多线程相关的知识,希望对你有一定的参考价值。
我正在编写一个Python程序,在主线程中,我一直在(循环中)使用recv函数通过TCP套接字接收数据。在回调函数中,我使用sendall函数通过同一个套接字发送数据。触发回调的原因是无关紧要的。我已将套接字设置为阻塞。
我的问题是,这样做安全吗?我的理解是在单独的线程(而不是主线程)上调用回调函数。 Python套接字对象是线程安全的吗?根据我的研究,我得到了相互矛盾的答案。
Python中的套接字不是线程安全的。
你试图立刻解决一些问题:
- 套接字不是线程安全的。
- recv阻塞并阻塞主线程。
- sendall正在从另一个线程使用。
您可以通过使用asyncio或以asyncio内部解决方式解决这些问题来解决这些问题:将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_queue
,它是要发送的数据队列。然后,我们创建一对连接的套接字(socketpair()
)。我们稍后需要这个以唤醒主线程,因为我们不希望recv()
阻止并阻止写入套接字。
然后,我们连接main_socket
并启动回调线程。现在这里是魔术:
在主线程中,我们使用select.select
来了解rsock
或main_socket
是否有任何数据。如果其中一个有数据,主线程就会唤醒。
在向队列添加数据后,我们通过发信号ssock
唤醒主线程,rsock
唤醒select.select
,从而从select.select()
返回。
为了完全理解这一点,你必须阅读socketpair()
,queue.Queue()
和qazxswpoi。
以上是关于Python Socket接收/发送多线程的主要内容,如果未能解决你的问题,请参考以下文章