Python 关闭线程服务器中的套接字和连接?

标签 python multithreading sockets python-multithreading

我们有一个 Python 套接字线程服务器示例。这是一个稍加修改的版本 https://stackoverflow.com/a/23828265/2008247 。该示例有效,并且我的测试证实它的性能比阻塞服务器更好。

但在示例中,套接字和连接对象并未关闭。这两个对象都有 close() 方法。 (连接上的 close 方法仅在异常时调用。我希望在每个连接结束时调用它。)我们不需要以某种方式调用它们吗?如果是这样,怎么办?

#!/usr/bin/env python

import socket
import threading

class ThreadedServer():

    def __init__(self, host, port):

        self.host = host
        self.port = port
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.sock.bind((self.host, self.port))

    def listen(self):

        self.sock.listen(5)

        while True:

            con, address = self.sock.accept()
            con.settimeout(60)
            threading.Thread(target=self.listenToClient,
                             args=(con, address)).start()

    def listenToClient(self, con, address):

        while True:
            try:
                data = con.recv(1024)
                if data:
                    # Set the response to echo back the recieved data
                    response = data
                    con.send(response)
                else:
                    raise Exception('Client disconnected')
            except:
                con.close()
                return False


def main():

    ThreadedServer('', 8001).listen()


if __name__ == "__main__":
    main()

最佳答案

根据[Python.Docs]: socket.close() :

Sockets are automatically closed when they are garbage-collected, but it is recommended to close() them explicitly, or to use a with statement around them.

因此,所有套接字最终都会被关闭。但是,如果服务器运行很长时间并且(快速)创建/销毁大量连接,您可能最终会遇到文件描述符耗尽的情况,因此无法创建新的套接字,因此它是最好手动关闭它们。

有2个案例。

1。关闭服务器套接字

事情很简单。添加一个“析构函数”,或者更好的:终结器 ( [Python.Docs]: Data model - object.__del__(self) ) 到您的 ThreadedServer 类中:

def __del__(self):
    #print("Closing server socket:", self.sock)
    self.sock.shutdown(socket.SHUT_RDWR)
    self.sock.close()

这并不是真正必要的,因为服务器将在程序结束时被销毁,并且所有资源无论如何都会在此时被释放。

2。关闭每个客户端套接字

或者:

  • finally 子句 ( [Python.Docs]: Compound statements - The try statement ) 添加到 listenToClient 中的 try (此时,您还可以将该方法重命名为类似 listen_to_client):

    # ...
    try:
        # Socket operation that might raise exceptions (con.recv)
    except:
        return False
    finally:
        #print("Closing connection:", con)
        con.shutdown(socket.SHUT_RDWR)
        con.close()
    
  • 扩展Thread类,并在ThreadedServer.listen中使用它(这更优雅):

    class ConnectionHandlingThread(threading.Thread):
        def __init__(self, target, connection, address):
            self.connection = connection
            super().__init__(target=target, args=(connection, address))
    
        def run(self):
            super().run()
            #print("Closing connection:", self.connection)
            self.connection.shutdown(socket.SHUT_RDWR)
            self.connection.close()
    

    及其用法:

    ConnectionHandlingThread(listen_to_client, con, address).start()
    

替代方案

这一切看起来有点像重新发明轮子。这个具体场景的样板已存在于 socketserver 模块(Python 标准库的一部分)中。更多详情请查看[Python.Docs]: socketserver - Asynchronous Mixins .

关于Python 关闭线程服务器中的套接字和连接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57841263/

相关文章:

C++ Ubuntu select() 如果串行接口(interface)有数据异步读取

java - 让java程序的一部分等待......而不是整个程序

c - Socket Programming in C : When client exit server, 服务器崩溃

python - 多维切片的紧凑符号

python - 如何将 std.error 写入文件,但将 std.out 写入 python 控制台?

java 多线程哈希 ArrayList<String>

python - 为什么我从套接字接收一个字符串,直到 python 中的\n 换行符转义序列?

python - 使用 Python 进行套接字编程 : Get the port of a server

python - 具有错误处理功能的 Geopy

python - 对 Python 程序进行 Debianzing 以获取 .deb