2011-12-08 12 views
1

私はlastest websocket specを使用してPythonでスレッドされたwebsocketサーバを作成しましたが、毎x秒ごとにすべてのクライアントにping要求を送信しようとしています。私はこれを行うために思い付いた唯一の方法は、このようなBaseServer.server_forever()をオーバーライドしている:ここではスレッドされたWebSocketサーバ(Python)のPingとPong

# override BaseServer's serve_forever to send a ping request every now and then 
class ModTCPServer(SocketServer.TCPServer): 
    def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True): 
     SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass, bind_and_activate) 
     self.__is_shut_down = threading.Event() 
     self.__shutdown_request = False 

    def serve_forever(self, poll_interval=0.5): 
     ### 
     global PING_EVERY_SEC 
     self.lastPing = int(time()) 
     ### 
     self.__is_shut_down.clear() 
     try: 
      while not self.__shutdown_request: 
       r, w, e = select.select([self], [], [], poll_interval) 
       if self in r: 
        self._handle_request_noblock() 
       ### 
       now = int(time()) 
       if (now - self.lastPing) >= PING_EVERY_SEC: 
        self.socket.send(WebSocketPing(['0x89','0x21','0xa7','0x4b'], now)) # arbitrary key 
        self.lastPing = now 
       ### 
     finally: 
      self.__shutdown_request = False 
      self.__is_shut_down.set() 

class LoginServer(SocketServer.ThreadingMixIn, ModTCPServer): 
    pass 

server = LoginServer(("", PORT), ApplicationHandler) 
print "serving at port", PORT 

server_thread = threading.Thread(target=server.serve_forever) 
server_thread.daemon = True 
server_thread.start() 

while server_thread.isAlive(): 
    pass 

server.shutdown() 

は、Pingフレームを構築する機能であり、それだけで内容にタイムスタンプを置く:バッド

def WebSocketPing(key, timestamp=False): 
    data = ['0x89','0x8a'] # 0x89 = fin,ping 0x8a = masked,len=10 
    data.extend(key) 
    if timestamp: 
     t = str(timestamp) 
    else: 
     t = str(int(time())) 
    for i in range(10): 
     masking_byte = int(key[i%4],16) 
     masked = ord(t[i]) 
     data.append(hex(masked^masking_byte)) 
    frame = '' 
    for i in range(len(data)): 
     frame += chr(int(data[i],16)) 
    return frame 

を私はこの

Traceback (most recent call last): 
    File "LoginServer.py", line 91, in <module> 
    server = LoginServer(("", PORT), ApplicationHandler) 
    File "LoginServer.py", line 63, in __init__ 
    SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass, bind_and_activate) 
    File "/usr/lib/python2.6/SocketServer.py", line 400, in __init__ 
    self.server_bind() 
    File "/usr/lib/python2.6/SocketServer.py", line 411, in server_bind 
    self.socket.bind(self.server_address) 
    File "<string>", line 1, in bind 
socket.error: [Errno 112] Address already in use 

を実行したときに物事が起こる私はこれがダウンしてPythonでか、この問題に対する根本的に間違ったアプローチの作品をオーバーライドする方法の理解の私の不足にあると仮定します。これを行うより良い方法や、このコードを動作させる方法はありますか?

答えて

3

コードでは、__is_shut_down__shutdown_requestのいずれのプロパティも設定されません。したがって、アクセスしようとして失敗します。このように、コンストラクタでそれらを作成します。

class ModTCPServer(SocketServer.TCPServer): 
    def __init__(self, *args, **kwargs): 
     SocketServer.TCPServer.__init__(self, *args, **kwargs) 
     self.__is_shut_down = threading.Event() 
     self.__shutdown_request = threading.Event() 

を更新に応じて:

socket.error: [Errno 112] Address already in use 

が別のプロセスがすでに指定されたポートにバインドされていることを意味します。 Unixでは、このプロセスは sudo netstat -ltpnで見つけることができます。または、別のポートを選択します。

+0

しかし、そのような属性はありません:/ – Dreen

+0

@Dreenそれを明確にすることはできますか? [pastebin](http://pastebin.com)で*完全な例と*正確な*エラーメッセージを投稿すると非常に役に立ちます。 – phihag

+0

phihagさん、ありがとう、私はそれがプロパティを認識させることができましたが、今は明らかにソケットが既に縛られているという問題があります - エラーメッセージ – Dreen

関連する問題