2011-09-13 1 views
2

複数のクライアントとの単純なサーバーを最適化:私は成功し、複数のクライアントを持つ単純なサーバー実装しました

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} 

それの何が問題になってい

は、ここでクライアントですか?

+0

1)をどのようにCPUの負荷が100になっていることを確認します%、2)あなたが使用している環境 – varela

+0

@varela:システムモニタ経由で。私はUbuntu 10.10を使用しています。 – qutron

答えて

1

私は、selectが書き込み可能なソケットがあると返します。そして、読み取り可能なソケットがなく、outstringが''のままであれば、すぐに繰り返しループを繰り返し実行するため、CPU負荷が高くなります。実際にデータを書き込む必要がある場合はwsocksを追加するほうがよいでしょう。選択呼び出しは、データが読み込めるまで待機します。あなたのコメントについては

、交換してください:

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

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

をしてfor sock in writes:アドオンの前に追加します。

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

それでは、スクリプトで何を変更する必要がありますか? – qutron

+0

私は答えを更新しました。 – rumpel

関連する問題