【问题标题】:How can I interrupt socket.accept() which is running in a different Thread in Python?如何中断在 Python 的不同线程中运行的 socket.accept()?
【发布时间】:2015-09-23 08:46:08
【问题描述】:

我想编写一个接受 tcp 连接的服务器,但我不想在调用 socket.accept() 时阻塞主线程,所以我想将网络放在不同的线程中。我已经看到无法中断 Python 中的线程,现在我想知道如何才能正确停止 socket.accept() 调用。

我想要的解决方案类似于 Java,例如:

class TcpServer:
    def waitForConnection():
        try:
            conn, addr = socket.accept()
        except ThreadInterrupt:
            # Close server ...

不幸的是,这个“ThreadInterrupt”并不存在。那么,我怎样才能实现这种行为呢?提前感谢每个提示。

【问题讨论】:

标签: python multithreading sockets


【解决方案1】:

您可以将套接字设置为非阻塞操作,并等待旧的 select 调用,等待它为 accept 做好准备(当它变得可读时) 第一次)。附加值是您可以侦听另一个文件 描述符,例如管道,这样您就可以进行特权通信 与您的线程建立通道,您可以随时退出线程:

import select
import socket
import os

class TcpServer:
    def __init__(self, ...):
        self.r_channel, self.w_channel = os.pipe() 
        self.socket = ...
    def waitForConnection(self):
        rfds, _, _ = select.select([self.socket.fileno(), self.r_channel],[],[])
        if self.r_channel in rfds:
            # close server
            ...
        self.socket.accept() # this won't block

# if you want to interrupt waitForConnection, from main thread:
os.write(tcp_server_object.w_channel, '!') # write something, just to wake up the select call

【讨论】:

  • 很好的答案,谢谢。您应该将行 if self.r_channel in rfds: 更改为 if self.r_channel in rfds[0]:,因为 rfds 是列表的三元组,我们正在第一个列表中搜索我们的 r_channel。有了这个更正,它对我有用。
  • 嗨!这很奇怪,因为在我的答案代码中,我得到了 select 在 3 个不同变量(rfds、_ 和 _)中返回的 3 个列表。您是否完全按照原样复制代码,或者您只是复制了rfds=select.select(...)
  • 当然,你是对的。我已经更改了代码并省略了下划线。很抱歉。
【解决方案2】:

您可以使用settimeout 并通过某个变量(在我的示例中为CONDITION)向线程发送信号:

CONDITION = False
s.settimeout(1.0)
while True:
    try:
        if CONDITION: break
        conn, addr = s.accept()
        break

    except socket.timeout as e:
        pass

在另一个线程中,您必须将 CONDITION 设置为 True,并且您可以在 while 块之后测试 CONDITION

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-04
    • 1970-01-01
    相关资源
    最近更新 更多