2011-12-08 86 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() 

這裏是構建平安框架的功能,它只是把時間戳的內容:

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)上發佈* complete *示例和* precise *錯誤消息,這將非常有幫助。 – phihag

+0

謝謝phihag,我設法讓它識別它的屬性,但是現在顯然,套接字已經綁定了一個問題 - 請參閱錯誤消息的問題 – Dreen