开发者

optimizing simple server with multiple clients

I've successfully implemented simple server with multiple clients:

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 just adds some fields

Everything works fine, but when client connects to server, CPU load goes to 100%.

Here's client:

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()

Here are profiler stats:

   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}

What's wrong with it?


I’d suggest that select returns that there is some writeable socket. And well, if there is no readable socket and outstring stays '', then you immediately run the loop again and again, causing high cpu load. So its probably better, to only add the wsocks if you actually need to write data. Then the select call will wait until data is available to read.

Concerning your comment, replace:

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

with

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

and add in front of for sock in writes: add:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜