关闭python线程中的监听套接字

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16734534/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 23:28:51  来源:igfitidea点击:

Close listening socket in python thread

pythonmultithreadingsockets

提问by Norling

I have a problem trying to learn about sockets for network communication. I have made a simple thread that listens for connections and creates processes for connecting clients, my problem though is that I can't get the thread to join properly as I haven't found a way to cancel the socket.accept()-call when I want to quit the program.

我在尝试了解用于网络通信的套接字时遇到问题。我制作了一个简单的线程来监听连接并为连接客户端创建进程,但我的问题是我无法让线程正确加入,因为我还没有找到取消 socket.accept() 调用的方法当我想退出程序时。

My code looks like this;

我的代码看起来像这样;

class ServerThread( threading.Thread ):

    def __init__(self, queue, host, port):
        threading.Thread.__init__(self)
        self.queue = queue
        self.running = True
        self.hostname = host
        self.port = port

    def run(self):
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.bind((self.hostname, self.port))
        self.socket.listen(1)
        while self.running:
            try:
                conn, address = self.socket.accept()
                process = Process(target=server_slave, args=(conn, address, self.queue))
                process.daemon = True
                process.start()
            except socket.timeout:
                pass

    def stop(self):
        self.running = False
        self.socket.close()

I have managed to get the program to close by setting self.setDaemon(True)and just exiting the main program, handing everything to the great garbage collector - but that seems like a bad solution. I've also tried setting a timeout for the socket but that results in getting [Errno 35] Resource temporarily unavailable(regardless of the actual timeout, even when I set it to years...).

我设法通过设置self.setDaemon(True)并退出主程序来关闭程序,将所有内容交给伟大的垃圾收集器 - 但这似乎是一个糟糕的解决方案。我还尝试为套接字设置超时,但这会导致[Errno 35] Resource temporarily unavailable(无论实际超时如何,即使我将其设置为年......)。

What am I doing wrong? Have I designed the thread in a dumb way or have I missed something about accepting connections?

我究竟做错了什么?我是否以愚蠢的方式设计了线程,或者我是否错过了有关接受连接的内容?

采纳答案by Norling

One way to get the thread to close seems to be to make a connection to the socket, thus continuing the thread to completion.

关闭线程的一种方法似乎是建立与套接字的连接,从而使线程继续完成。

def stop(self):
    self.running = False
    socket.socket(socket.AF_INET, 
                  socket.SOCK_STREAM).connect( (self.hostname, self.port))
    self.socket.close()

This works, but it still feels like it might not be optimal...

这有效,但仍然感觉它可能不是最佳的......

回答by Eddie

In most cases you will open a new thread or process once a connection is accepted. To close the connection, break the while loop. Garbage collection will remove the thread or process but join will ensure none get left behind.

在大多数情况下,一旦连接被接受,您将打开一个新线程或进程。要关闭连接,请中断 while 循环。垃圾收集将删除线程或进程,但加入将确保不会留下任何东西。

Persistent sockets close when the user closes them or they timeout. Non-persistent, like static webpages will close after they've sent the information.

持久套接字在用户关闭它们或超时时关闭。非持久性的,如静态网页在发送信息后将关闭。

Here's a good example of a persistent socket server in Python. It uses multiprocessing which means it can run across multiple cores for CPU-bound tasks. More commonly known as multithreading.

这是 Python 中持久套接字服务器的一个很好的示例。它使用多处理,这意味着它可以跨多个内核运行以执行受 CPU 限制的任务。通常称为多线程。

import socket
import multiprocessing

def run():
    host = '000.000.000.000'
    port = 1212
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind(('', port))
    sock.listen(3)
    while True:
        p = multiprocessing.Process(target=worker, args=sock.accept()).start()
def worker(conn, addr):
    while True:
        if data == '':
            #remote connection closed
            break
         if len(dataList) > 2:
            # do stuff
            print 'This code is untested'

run()

回答by Alex V.

Partially tested solution

部分测试的解决方案

  1. Put self.socket.settimeout(0.1)right before while
  2. Put conn.settimeout(None)right after accept
  1. 放在self.socket.settimeout(0.1)前面while
  2. 紧随conn.settimeout(None)其后accept

回答by Jean-Fran?ois Fabre

A dirty solution which allows to exit your program is to use os._exit(0).

允许退出程序的肮脏解决方案是使用os._exit(0).

def stop(self):
    self.socket.close()
    os._exit(0)

note that sys.exitdoesn't work/blocks as it tries to exit cleanly/release resources. But os._exitis the most low level way and it works, when nothing else does.

请注意,sys.exit当它尝试干净地退出/释放资源时,它不起作用/阻塞。但os._exit它是最底层的方式,它可以工作,而其他什么都没有。

The operating system itself will release the resources (on any modern system) like when doing exitin a C program.

操作系统本身会释放资源(在任何现代系统上),就像exit在 C 程序中一样。