Skip to main content
 首页 » 编程设计

python之优化具有多个客户端的简单服务器

2025年05月04日7虾米姐

我已经成功地实现了具有多个客户端的简单服务器:

class ProcessingServer: 
    def __init__(self, bindaddress="127.0.0.1", portname=50001, maxqueue=5): 
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
        self.socket.bind((bindaddress, portname)) 
        self.socket.listen(maxqueue) 
        self.inputsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
        self.data = [] 
 
    def start(self): 
        rsocks, wsocks = [], [] 
        rsocks.append(self.socket) 
        rsocks.append(self.inputsocket) 
        print "Waiting for connection..." 
        self.inputsocket.connect(("192.168.1.1", 1234)) 
        print "Connected." 
        clients = [] 
 
        try: 
            while True: 
                try: 
                    reads, writes, errs = select.select(rsocks, wsocks, []) 
                except: 
                    return 
                for sock in reads: 
                    if sock == self.socket: 
                        client, address  = sock.accept() 
                        print "Client ", address, " connected" 
                        wsocks.append(client) 
                        clients.append(client) 
                    elif sock == self.inputsocket: 
                        self.data.append(sock.recv(256)) 
 
                outstring = ""  
                if len(self.data) > 1: 
                    msg_list = self.data[0].split('\n') 
                    for msg in msg_list: 
                        if msg != '': 
                            curr_msg = msg.split(',') 
                            process_message(curr_msg) 
                            outstring = ','.join(curr_msg) 
                            print curr_msg 
                    self.data = [] 
 
                for sock in writes:  
                    if sock in clients: 
                        if outstring != "": 
                            sock.send(outstring) 
 
        except KeyboardInterrupt: 
            print "Server was stopped" 
            self.inputsocket.close() 
            self.socket.close() 
            for sock in writes: 
                sock.close() 
            for sock in reads: 
                sock.close() 
            for sock in clients: 
                sock.close() 

process_message只是增加了一些字段

一切正常,但是当客户端连接到服务器时,CPU 负载达到 100%。

这是客户:

import socket 
mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
mysocket.connect(("127.0.0.1", 50001)) 
while True: 
    data = mysocket.recv(512) 
mysocket.close() 
outfile.close() 

以下是分析器统计信息:

   ncalls  tottime  percall  cumtime  percall filename:lineno(function) 
        1    0.000    0.000   34.563   34.563 <string>:1(<module>) 
        1    0.000    0.000    0.000    0.000 <string>:1(bind) 
        1    0.000    0.000    0.000    0.000 <string>:1(connect) 
  6870763    6.408    0.000    9.030    0.000 <string>:1(fileno) 
        1    0.000    0.000    0.000    0.000 <string>:1(listen) 
        1    0.000    0.000    0.000    0.000 server.py:113(__init__) 
        1    4.409    4.409   34.556   34.556 server.py:123(start) 
        1    0.007    0.007   34.563   34.563 server.py:176(main) 
       91    0.002    0.000    0.010    0.000 server.py:80(process_message) 
        3    0.000    0.000    0.000    0.000 socket.py:182(__init__) 
        1    0.000    0.000    0.000    0.000 socket.py:196(accept) 
       18    0.000    0.000    0.000    0.000 {getattr} 
  2290358    0.906    0.000    0.906    0.000 {len} 
        1    0.000    0.000    0.000    0.000 {method 'accept' of '_socket.socket' objects} 
      186    0.000    0.000    0.000    0.000 {method 'append' of 'list' objects} 
        1    0.000    0.000    0.000    0.000 {method 'bind' of '_socket.socket' objects} 
        1    0.000    0.000    0.000    0.000 {method 'connect' of '_socket.socket' objects} 
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects} 
  6870763    2.622    0.000    2.622    0.000 {method 'fileno' of '_socket.socket' objects} 
      273    0.000    0.000    0.000    0.000 {method 'insert' of 'list' objects} 
       91    0.000    0.000    0.000    0.000 {method 'join' of 'str' objects} 
        1    0.000    0.000    0.000    0.000 {method 'listen' of '_socket.socket' objects} 
      182    0.001    0.000    0.001    0.000 {method 'recv' of '_socket.socket' objects} 
       71    0.001    0.000    0.001    0.000 {method 'send' of '_socket.socket' objects} 
      182    0.000    0.000    0.000    0.000 {method 'split' of 'str' objects} 
  2290268   20.197    0.000   29.227    0.000 {select.select} 
       18    0.000    0.000    0.000    0.000 {setattr} 

这是怎么回事?

请您参考如下方法:

我建议 select 返回有一些可写套接字。好吧,如果没有可读的套接字并且 outstring 停留在 '',那么您会立即一次又一次地运行循环,从而导致高 cpu 负载。因此,如果您确实需要写入数据,则只添加 wsocks 可能更好。然后 select 调用将等待数据可供读取。

关于您的评论,替换为:

reads, writes, errs = select.select(rsocks, wsocks, []) 

与

reads, writes, errs = select.select(rsocks, [], []) 

并在前面添加for sock in writes: 添加:

reads, writes, errs = select.select([], wsocks, [], 0)