【问题标题】:Python closing socket and connection in a threaded server?Python在线程服务器中关闭套接字和连接?
【发布时间】:2019-09-08 10:52:30
【问题描述】:

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

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

#!/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 multithreading sockets python-multithreading


    【解决方案1】:

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

    套接字在被垃圾回收时会自动关闭,但建议明确地close() 它们,或在它们周围使用with 语句。

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

    两种情况:

    1。关闭服务器套接字

    事情很简单。将“析构函数”或更好的:终结器 ([Python 3.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。关闭每个客户端套接字

    • listenToClient 中的 try 中添加 finally 子句 ([Python 3.Docs]: Compound statements - The try statement)(此时您也可以重命名listen_to_client 之类的方法):

      # ...
      try:
          # ...
      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 3.Docs]: socketserver - Asynchronous Mixins

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-21
    • 1970-01-01
    • 2013-02-17
    • 1970-01-01
    相关资源
    最近更新 更多