【问题标题】:Why is my TCPServer not accepting multiple client connections?为什么我的 TCPServer 不接受多个客户端连接?
【发布时间】:2021-09-13 06:39:56
【问题描述】:

我在TCP服务器下面写了,不知道为什么handler不支持多个TCP客户端连接。

import socket
import sys
import ast

# Internal imports
import core
try:
    import fcntl
except ImportError:
    fcntl = None
import logging
import json

_LOG = logging.getLogger(__name__)

if sys.version_info.major == 2:
    import SocketServer
    TCPServer = SocketServer.TCPServer
    RequestHandler = SocketServer.BaseRequestHandler
if sys.version_info.major == 3:
    import socketserver
    TCPServer = socketserver.TCPServer
    RequestHandler = socketserver.BaseRequestHandler


class TCPServerRequestHandler(RequestHandler):

    def handle(self):
        """Receives data from client.
        """
        msg = self.request.recv(1024).strip()
        if self.client_address and not msg:
            _LOG.error("No Data revieved from Client: {}".format(self.client_address[0]))
            return
        # Send some data to client
        # self.wfile.write("Hello Client....Got your message".encode())
        data = ast.literal_eval(msg.decode('utf-8'))
        if not data:
            _LOG.error("No data recieved.")
        else:
            with core._connect(db="exampledb") as conn:
                if "device" in data and data["device"] == "mcu":
                    table_name = "roku_online_status"
                    if conn:
                        data.pop("device")
                        cols = [c for c in data.keys()] # python 3 dict keys is not list
                        stored_value = core.doQuery(conn, table_name, cols, "id")
                        if stored_value[0] != data["online"]:
                            core.insert_row(data, table_name, conn)
                else:
                    if conn:
                        core.insert_row(data, "particle_photon", conn)
                conn.close()


class Server(TCPServer):
    allow_reuse_address = True
    # The constant would be better initialized by a systemd module
    SYSTEMD_FIRST_SOCKET_FD = 3

    def __init__(self, server_address, handler_cls, bind_and_activate=True):
        self.handlers = set()
        # Invoke base but omit bind/listen steps (performed by systemd activation!)
        try:
            TCPServer.__init__(self, server_address, handler_cls, bind_and_activate)
        except TypeError:
            TCPServer.__init__(self, server_address, handler_cls)

        # Override socket
        self.socket = socket.fromfd(
            self.SYSTEMD_FIRST_SOCKET_FD, self.address_family, self.socket_type)

        if fcntl is not None and hasattr(fcntl, 'FD_CLOEXEC'):
            flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD)
            flags |= fcntl.FD_CLOEXEC
            fcntl.fcntl(self.fileno(), fcntl.F_SETFD, flags)

    def server_bind(self):
        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.socket.bind(self.server_address)

    def server_close(self):
        TCPServer.server_close(self)
        print("Shutting down server.")
        for handler in self.handlers.copy():
            print(handler)
            self.shutdown_request(handler.request)


def main(server_address):
    """Starts TCPServer.
    """
    logging.basicConfig(level=logging.DEBUG)
    # Create a TCP Server instance
    server = Server(server_address, TCPServerRequestHandler)
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        sys.exit(0)


if __name__ == '__main__':
    main(("10.10.10.2", 7111))

对于单个连接,它可以正常工作,但是当多个客户端尝试连接时,它会卡住。

【问题讨论】:

  • 卡在哪里了?

标签: python-3.x sockets tcpclient tcpserver


【解决方案1】:

您已经实现了具有阻塞 I/O 的单线程服务器。这种服务器一次只能处理一个客户端,因为它会等到客户端完成(在TCPServerRequestHandler 内)才能处理下一个客户端的连接。

要同时处理多个客户端,您要么必须使用多个线程或进程,每个线程或进程都可以处理单个客户端,要么您必须实现一个基于事件的服务器,该服务器可以在单个线程中处理多个客户端。要实现第一个,您可以查看ThreadingTCPServerForkingTCPServer,对于后者,请查看Twisted 之类的框架。

【讨论】:

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