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")
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
4.一般websocket需要加验证,否则各种非法连接进来可咋整,加个token装饰器就可以了
5.提供两个在线测试工具
http://www.blue-zero.com/WebSocket/
http://coolaf.com/tool/chattest
注释:
ws.state 查看ws链接状态
ws.close 关闭链接