оптимизация простого сервера с несколькими клиентами - PullRequest
2 голосов
/ 13 сентября 2011

Я успешно реализовал простой сервер с несколькими клиентами:

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 просто добавляет некоторые поля

Все работает нормально, но когда клиент подключается к серверу, загрузка процессора идетна 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}

Что с этим не так?

1 Ответ

1 голос
/ 14 сентября 2011

Я бы предположил, что select возвращает наличие какого-либо записываемого сокета.И хорошо, если нет читаемого сокета, а выходное значение остается '', то вы немедленно запускаете цикл снова и снова, вызывая высокую загрузку процессора.Так что, вероятно, лучше добавлять 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...