sanic之websocket路由

在某些时候,需要建立websocket路由,来建立长链接,来实时传输数据,就比如一些聊天应用,就有实时音视频,需要实时传出状态

在sanic框架中支持两种websocket路由方式,有一种是再app中建立,另一种实在蓝图中,但是没有提供类的路由写法,都是通过函数的写法

1.app

from sanic import Sanic
app = Sanic(__name__)

@app.websocket('/feed')
async def feed(request, ws):
    try:
        while True:
            data = 'hello!'
            print('Sending: ' + data)
            await ws.send(data)
            data = await ws.recv()
            print('Received: ' + data)
    except Exception as e:
        print(e)

#app.add_websocket_route(feed, "/feed")
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8009) 

2.blueprint

接口:ws://ip号:8001/api/student/v2/feed

StudentVideoCallBP = Blueprint(__name__, url_prefix='/api/student/v2/')

@StudentVideoCallBP.websocket('/feed')
async def feed(ws):
    try:
        while True:
            data = 'hello!'
            print('Sending: ' + data)
            await ws.send(data)
            data = await ws.recv()
            print('Received: ' + data)
    except Exception as e:
        print(e)


# StudentVideoCallBP.add_websocket_route(feed, "/feed")
View Code

3.略微复杂的一个小demo,写的是一个客户端和服务端实时通信,接口ws://10.130.145.200:8001/api/student/v2/wxlink/5ad85e49705deb4d3b98c111

async def wxLink(request, ws, studentMid):
    student = await Student.find_one(studentMid, as_raw=True)
#循环监听是否有客户端链接,
    while True:
#try客户端链接状态
        try:
#try判断是数据是否有这个学生id
            try:
                if not student:
#告诉客户端id错误,可能是个非法链接,然后主动断开非法链接
                    await ws.send(osjson.dumps(
                        {"studentMid": "", "videoRoomId": "", 'userSig': "", 'privateMapKey': "", 'sdkAppId': ""}))
                    break
                Rucode = student['Rucode']
                key = studentMid + '_' + Rucode
                videoStatus = await ws.recv()
                if videoStatus == '0' and str(ws.state) == 'State.OPEN':
                    data = await VideoData.get(key)
                    if data:
                        value = osjson.loads(data)
                        roomId = value['videoRoomId']
                        privateMapKey = value['privateMapKey']
                        sdkAppId = str(value['sdkAppId'])
                        userSig = str(value['user_userSig'])
                        status = value['status']
                        IsAvailable = value['IsAvailable']
                        if status == 0 and str(ws.state) == 'State.OPEN' and IsAvailable == 1:
                            await ws.send(osjson.dumps({"studentMid": "ok", 'videoRoomId': roomId, 'userSig': userSig,
                                                        'privateMapKey': privateMapKey, 'sdkAppId': sdkAppId}))
                        elif status == 0 and str(ws.state) == 'State.OPEN' and IsAvailable == 2:
                            await ws.send(osjson.dumps(
                                {"studentMid": "ok", 'videoRoomId': "", 'userSig': "",
                                 'privateMapKey': "", 'sdkAppId': ""}))


                # 确认接收到roomId
                elif videoStatus == '1':
                    data = await VideoData.get(key)
                    if data:
                        value = osjson.loads(data)
                        value['status'] = 1
                        doc = osjson.dumps(value)
                        await VideoData.set(key, doc)

                # 接通成功
                elif videoStatus == '2':
                    value = await VideoData.get(key)
                    if value:
                        await VideoData.delete(key)
                    else:
                        pass
                # 拒绝接通
                elif videoStatus == '3':
                    req = await VideoData.get(key)
                    if req:
                        classRoomUid = osjson.loads(req)['classRoomUid']
                        await VideoData.delete(key)
                        # 推送消息
                        push_title = "I40001"
                        message = '对方已拒绝'
                        try:
                            await pushmsg(student['Rucode'], classRoomUid, push_title, message)
                        except Exception as e:
                            print(e)
                elif videoStatus == '3':
                    req = await VideoData.get(key)
                    if req:
                        await VideoData.delete(key)
                else:
                    pass
            except TypeError:
                ws.close()
#监听如果客户端断开链接,则服务端退出循环,断开链接
        except ConnectionClosed:
            break
View Code

4.一般websocket需要加验证,否则各种非法连接进来可咋整,加个token装饰器就可以了

5.提供两个在线测试工具

http://www.blue-zero.com/WebSocket/

http://coolaf.com/tool/chattest

注释:

ws.state   查看ws链接状态
ws.close 关闭链接

 

posted on 2018-10-11 21:07  V神丫丫  阅读(2510)  评论(1编辑  收藏  举报