无法从内部停止套接字服务器线程

问题描述 投票:0回答:1

我有以下情况:
我有一个名为 Server 的类,顾名思义,该类启动服务器并应该停止它。这是代码:

import socket
import threading


class Server:
    def __init__(self, server_manager, host, port, running):
        # Define the host and port to listen on
        self.host = host
        self.port = port

        self.server_manager = server_manager

        # setting stop event up
        self.running = running

        # Create a socket object
        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # Bind the socket to the host and port
        self.server.bind((self.host, self.port))

        # Start listening for up to 5 incoming connections
        self.backlog = 5
        self.server.listen(self.backlog)

    def run(self):
        while not self.running.is_set():
            try:
                # Accept a connection from a client
                client_socket, client_address = self.server.accept()

                client_handler = threading.Thread(target=self.handle_client, args=(client_socket,))
                client_handler.start()
            except socket.error:
                pass

    def handle_client(self, client_socket):
        while not self.running.is_set():
            try:
                client_data = client_socket.recv(1024)  # Receive data from the client
                if not client_data:
                    break

                # Process the received data here

                self.server_manager.show_data(client_data)

                # Send a response back to the client (optional)
                response = "Successfully sent data! Now responding!"
                client_socket.send(response.encode('utf-8'))

            except Exception as e:
                print(f"Error: {e}")
            finally:
                client_socket.close()

        client_socket.close()

    def close(self):
        # close
        pass

我还有一个名为 ServerManager 的类,它处理来自服务器的数据。再次代码:

import threading
from ConnectionProcessor.connection import Server


class ServerManager:
    def __init__(self, host="127.0.0.1", port=6969):
        self.host = host
        self.port = port

        self.running = threading.Event()

        self.server = Server(server_manager=self, host=self.host, port=self.port, running=self.running)
        self.server_thread = threading.Thread(target=self.server.run)
        self.server_thread.start()

    def close(self):
        self.running.set()

    def show_data(self, data: str):
        print(data)

效果很好,我可以打印来自服务器的数据。我唯一的问题是,我无法从主类关闭服务器:

from ConnectionProcessor import ServerManager
from time import sleep

if __name__ == "__main__":
    server_manager = ServerManager()
    sleep(4)
    server_manager.close()

服务器仍在运行。

我尝试了多种方法,也尝试将 self.running 从 threading.Event 更改为简单的 bool,但它具有相同的效果,但不起作用。

这是我第一次使用线程和套接字,也许这只是一个简单的错误。

python multithreading sockets connection python-multithreading
1个回答
0
投票

该问题与您在 Server 类中处理 self.running 事件的方式有关。 Server 类中的 run 方法有一个 while 循环,只要 self.running 未设置,该循环就会继续。但是,当您调用 close 方法时,似乎 self.running 事件没有正确设置。

让我们做一些修改,以确保在调用 close 方法时设置 self.running 事件

  1. 更新ServerManager类中的close方法以关闭 服务器:

    服务器管理器类: # ...(其他方法)

    def close(self):
        self.running.set()  # Set the running event
        self.server.close()  # Close the server
    
  2. 更新Server类中的close方法,关闭服务器 插座:

    类服务器: # ...(其他方法)

    def close(self):
        self.running.set()  # Set the running event
        self.server.close()  # Close the server socket
    
  3. 修改Server类中run方法中的while循环来检查 运行事件和服务器套接字状态:

    类服务器: # ...(其他方法)

    def run(self):
        while not self.running.is_set():
            try:
                # Accept a connection from a client
                client_socket, client_address = self.server.accept()
    
                client_handler = threading.Thread(target=self.handle_client, args=(client_socket,))
                client_handler.start()
            except socket.error:
                if self.running.is_set():
                    break  # Break the loop if running is set
                else:
                    continue  # Continue the loop if it's a different socket error
    
    # ... (other methods)
    

这些更改确保 Server 和 ServerManager 类在调用 close 方法时设置 self.running 事件,并且 Server 类的 run 方法中的 while 循环检查运行事件和服务器套接字状态。

现在,当您调用 server_manager.close() 时,它应该正确设置事件并关闭服务器,从而允许服务器正常停止。

© www.soinside.com 2019 - 2024. All rights reserved.