如何计算TCPServer中的连接客户端数量?

4 投票
2 回答
4928 浏览
提问于 2025-04-16 14:05

我正在使用Python的SocketServer.ThreadingTCPServer。现在我想知道在某个时刻有多少个客户端连接着。

这个问题怎么解决呢?

2 个回答

0

在一个负责“服务”客户端的线程中,有一个全局计数器,当客户端连接时这个计数器会增加,断开连接时会减少。

如果你想从操作系统的层面来统计连接数,可以使用 nestat -an 命令,并配合合适的 grep 过滤器和 wc -l 命令(在Windows上需要使用 grepwc 的移植版本)。

6

SocketServer.ThreadingTCPServer 会为每个连接的客户端创建一个新的线程,所以在某一时刻知道有多少个客户端连接,就等于知道有多少个线程在活动。你只需要使用 threading.activeCount,这样就能得到当前的客户端数量:

num_client = threading.activeCount() - 1 # Don't count the main thread.

当然,如果你的代码中还有其他地方也在创建线程,这样的方法就不一定准确了。为了修正这个问题,你可以重写 process_request() 和 process_request_thread() 这两个方法,增加一个客户端计数器。

根据这个例子 这里,我写了这段代码来测试这两种方法:

import time
import socket
import threading
from SocketServer import ThreadingTCPServer, BaseRequestHandler


def client(ip, port, message):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((ip, port))
    sock.send(message)
    response = sock.recv(1024)
    sock.close()


class ThreadedTCPRequestHandler(BaseRequestHandler):

    def handle(self):
        data = self.request.recv(1024)
        cur_thread = threading.currentThread()
        response = "%s: %s" % (cur_thread.getName(), data)
        self.request.send(response)
        time.sleep(1)


class MyServer(ThreadingTCPServer):

    def __init__(self, *args, **kws):
        self._num_client = 0
        ThreadingTCPServer.__init__(self, *args, **kws)

    def process_request(self, *args, **kws):
        print "swap thread"
        self._num_client += 1
        ThreadingTCPServer.process_request(self, *args, **kws)

    def process_request_thread(self, *args, **kws):
        ThreadingTCPServer.process_request_thread(self, *args, **kws)
        print "kill thread"
        self._num_client -= 1

    def get_client_number(self):
        return self._num_client


def my_client_count(ignore=1):
    return  threading.activeCount() - ignore


if __name__ == '__main__':
    server = MyServer(("localhost", 0), ThreadedTCPRequestHandler)

    server_thread = threading.Thread(target=server.serve_forever)
    ip, port = server.server_address

    server_thread.setDaemon(True)
    server_thread.start()

    print "client 1 connected"
    client(ip, port, "Hello World 1")
    print "number of client get_client_number : %s,  enumerate : %s" \
       %  (server.get_client_number(), my_client_count())
    print "client 2 connected"
    client(ip, port, "Hello World 2")
    print "number of client get_client_number : %s,  enumerate : %s" \
       %  (server.get_client_number(), my_client_count())

    time.sleep(3)
    print "client 3 connected"
    client(ip, port, "Hello World 3")
    print "number of client get_client_number : %s,  enumerate : %s" \
       %  (server.get_client_number(), my_client_count())

输出结果:

client 1 connected
swap client thread
number of client get_client_number : 1,  enumerate : 2
client 2 connected
swap client thread
number of client get_client_number : 2,  enumerate : 3
kill client thread
kill client thread
client 3 connected
swap client thread
number of client get_client_number : 1,  enumerate : 2

正如你所看到的,第二种方法给出的值更准确。两种方法的区别在于,因为我的服务器是用线程运行的,所以总是多了一个线程,这就解释了结果差1的原因。

希望这能帮到你 :)

撰写回答