websocket 的实现来了
#websocket.py
#!/usr/bin/python2.7/bin/python
# -*- coding: utf-8 -*-
from eurasia.socket2 import error
from eurasia.core import schedule
import collections
from struct import *
import string
import hashlib
def get_headers(httpfile):
bytes = httpfile.sockfile.read(8)
getenv = httpfile.environ.get
resource = httpfile.path_info
host = getenv('HTTP_HOST', '')
origin = getenv('HTTP_ORIGIN', '')
key1 = getenv('HTTP_SEC_WEBSOCKET_KEY1', '')
key2 = getenv('HTTP_SEC_WEBSOCKET_KEY2', '')
return [resource, host, origin, key1, key2, bytes]
def part(token):
out = ""
spaces = 0
for char in token:
if char in string.digits:
out += char
elif char == " ":
spaces += 1
return int(out) / spaces
def WebSocketHttpHandler(func):
def Function(*args, **kargs):
handshake(args[0])
ws = WebSocket(*args)
return func(ws, **kargs)
return Function
def handshake(httpfile):
client = httpfile.sockfile
headers = get_headers(httpfile)
challenge = pack('>LL', part(headers[3]), part(headers[4])) + headers[5]
hash = hashlib.md5(challenge).digest()
our_handshake = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"+"Upgrade: WebSocket\r\n"+"Connection: Upgrade\r\n"+"Sec-WebSocket-Origin: "+headers[2]+"\r\n"+"Sec-WebSocket-Location: "+" ws://"+headers[1]+headers[0]+"\r\n\r\n"
client.sendall(our_handshake.encode('latin-1') + hash)
class WebSocket(object):
def __init__(self, httpfile):
self.socket = httpfile.sockfile
self.websocket_closed = False
self._buf = ""
self._msgs = collections.deque()
@staticmethod
def _pack_message(message):
if isinstance(message, unicode):
message = message.encode('utf-8')
elif not isinstance(message, str):
message = str(message)
return "\x00%s\xFF" % message
def _parse_messages(self):
msgs = []
end_idx = 0
buf = self._buf
while buf:
frame_type = ord(buf[0])
if frame_type == 0:
# Normal message.
end_idx = buf.find("\xFF")
if end_idx == -1: #pragma NO COVER
break
msgs.append(buf[1:end_idx].decode('utf-8', 'replace'))
buf = buf[end_idx+1:]
elif frame_type == 255:
# Closing handshake.
assert ord(buf[1]) == 0, "Unexpected closing handshake: %r" % buf
self.websocket_closed = True
break
else:
raise ValueError("Don't understand how to parse this type of message: %r" % buf)
self._buf = buf
return msgs
def read(self, size=8192, timeout=-1):
while not self._msgs:
if self.websocket_closed:
return None
delta = self.socket.recv(size, timeout)
if delta == '':
return None
self._buf += delta
msgs = self._parse_messages()
self._msgs.extend(msgs)
return self._msgs.popleft()
def sendall(self, message, timeout=-1):
packed = self._pack_message(message)
while getattr(self.socket, 'writing', 0):
schedule()
self.socket.writing = 1
self.socket.sendall(packed, timeout)
self.socket.writing = 0
def close(self):
self.socket.close()
#使用方法如下
#!/usr/bin/python2.7/bin/python
# -*- coding: utf-8 -*-
from eurasia.socket2 import error
from eurasia.core import timeout
from eurasia.web import httpserver, mainloop
from eurasia import core
import sys
from traceback import print_exc
from time import time
from datetime import datetime
import websocket2
# 安装调试钩子
core.excepthook = lambda: print_exc(file=sys.stderr)
def broadcast(msg):
'''廣播消息'''
now = datetime.fromtimestamp \
(time()).strftime('%Y-%m-%d %H:%M:%S')
msg = '%s ~ %s' % (msg, now)
try:
for sock in sockfiles:
sock.sendall(msg)
except:
pass
@websocket2.WebSocketHttpHandler
def handler(ws):
sockfiles.add(ws)
try:
while 1:
s = ws.read()
if s is None:
break
broadcast('%s' % (s.strip(),))
ws.close()
finally:
sockfiles.remove(ws)
sockfiles = set()
httpd = httpserver(('', 2345), handler)
httpd.start()
mainloop()