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())
1 回答
Python中的套接字不是线程安全的 .
你试图立刻解决一些问题:
套接字不是线程安全的 .
recv阻塞并阻塞主线程 .
sendall正在使用其他线程 .
您可以通过使用asyncio解决这些问题,或者像asyncio在内部解决它一样解决这些问题:将
select.select
与socketpair
一起使用,并使用队列作为传入数据 .我们在这里使用多个构造 . 您必须使用您选择的代码填充空白区域 . 至于解释:
我们首先创建一个
send_queue
,它是要发送的数据队列 . 然后,我们创建一对连接的套接字(socketpair()
) . 我们稍后需要这个以唤醒主线程,因为我们不希望recv()
阻止并阻止写入套接字 .然后,我们连接
main_socket
并启动回调线程 . 现在这里是魔术:在主线程中,我们使用
select.select
来了解rsock
或main_socket
是否有任何数据 . 如果其中一个有数据,主线程就会唤醒 .在向队列添加数据后,我们通过发出
ssock
信号来唤醒主线程,它唤醒了rsock
,从而从select.select
返回 .为了完全理解这一点,你必须阅读select.select(),socketpair()和queue.Queue() .