Eurasia 3.1 能否內建websocket 接口

26 views
Skip to first unread message

bawbaw hu

unread,
Apr 2, 2011, 8:40:48 PM4/2/11
to eurasi...@googlegroups.com
Hi 沈大,

之前試了好多websocket lib,但都極其不穩定,想問問,您那邊有實現好的嗎?

bawbaw hu

unread,
Apr 2, 2011, 11:33:51 PM4/2/11
to eurasi...@googlegroups.com

沈崴

unread,
Apr 5, 2011, 10:35:40 PM4/5/11
to eurasia-users
事实上 eurasia web server 的普通接口本身,已经是类似 socket file 的形式。
不仅能完成 web socket 所有的功能,而且要更优雅一些(比如 js rpc)。

我个人认为使用 web socket 编写相同的应用,很难做到像 eurasia 一样便捷,因此
官方没有实现 web socket 的计划,不过大家可以尝试自己实现一下 :)

要获得完整的 socket 能力,可以使用 eurasia 的 socket server。

On 4月3日, 上午3时33分, bawbaw hu <bawbaw...@gmail.com> wrote:
> 就像http://eventlet.net/doc/examples.html#websocket-server-example
>
> 有提供內建的 handler

沈崴

unread,
Apr 6, 2011, 8:39:01 AM4/6/11
to eurasia-users
啊哈,和很久以前那个 orbited 项目搞混淆了,弄错了,弄错了。

bawbaw 提到的应该是 html5 里的 web socket,真是抱歉。这个应该支持的。

我简单看了下协议,目前在 eurasia 中使用 web socket 的方法如下:

status = '101 WebSocket Protocol Handshake'
headers = [('Upgrade', 'WebSocket'), ('Connection', 'Upgrade')]

def handler(httpfile):
# 判断是否为 web socket 请求
getenv = httpfile.environ.get
if 'upgrade' == getenv('connection', '').lower() and
'websocket' == getenv('upgrade' , '').lower():
httpfile.start_response(status, headers)
tcphandler(httpfile.sockfile)
return httpfile.shutdown()
else:
httpfile.shutdown()

def tcphandler(sockfile):
...

—— 很简单,不是吗 ;)

bawbaw hu

unread,
Apr 6, 2011, 8:24:06 PM4/6/11
to eurasi...@googlegroups.com
感谢沈大,提供一些关键eurasia 接口,这比实现wsgi 更方便,我已实现纯tcp 的 websocket,等我搞定后再上来分享。^^

--
您收到此邮件是因为您订阅了 Google 网上论坛的“eurasia-users”论坛。
要向此网上论坛发帖,请发送电子邮件至 eurasi...@googlegroups.com
要取消订阅此网上论坛,请发送电子邮件至 eurasia-user...@googlegroups.com
若有更多问题,请通过 http://groups.google.com/group/eurasia-users?hl=zh-CN 访问此网上论坛。


bawbaw hu

unread,
Apr 8, 2011, 4:33:29 AM4/8/11
to eurasi...@googlegroups.com
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()
Reply all
Reply to author
Forward
0 new messages