aiohttp websocket 简单使用

import aiohttp
from aiohttp import web

personal_pool = {}
room_pool = {}

# 发送消息
async def broadcast_msg(user_name,msg,room=""):

    # 如果不是聊天室,则单独返回
    if not room:
        ws = personal_pool[user_name]
        await ws.send_str("服务器接收到了您的信息")
    # 如果是聊天室则广播
    else:
        users = room_pool[room]
        for name,ws in users.items():
            if user_name != name :
                await ws.send_str(user_name + " -> " + msg)

async def delete_ws():
    pass


async def hello(request):
    return web.Response(text="Hello, world")


async def websocket_handler(request):

    # ws对象
    ws = web.WebSocketResponse()
    # 等待用户连接
    await ws.prepare(request)

    room = request.query.get('room')
    user_name = request.query.get('user_name')
    print("room",room)
    print("user_name",user_name)

    # -------------------------------------------------------------------
    # 这一大段,都是存储ws的逻辑
    # 如果是聊天室,则存入 room_pool , { "room1":{"张三":ws1,"李四":ws2}}
    # 如果不是聊天室,则是和服务器的私人交互,personal_pool, {"张三":ws1,"李四":ws2}
    # 退出的时候,要删除对应的ws,这里没写

    if room:
        if room in room_pool:
            room_pool[room][user_name] = ws
        else:
            room_pool[room] = {user_name:ws}

    else:
        if user_name in personal_pool:
            await ws.send_str("名字已有")
            print('websocket connection closed')
            return ws
        else:
            personal_pool[user_name] = ws
    # -------------------------------------------------------------------

	# 阻塞住,等待用户的消息
	# websocket 可以理解 http请求,但是连接一直不断开
	# 然后服务器不断的返回一些数据
	# 直到最后return ws ,相当于http的response,然后就断开连接了
    async for msg in ws:
        if msg.type == aiohttp.WSMsgType.TEXT:
            if msg.data == 'close':
                await ws.close()
            else:
                await broadcast_msg(user_name,msg.data,room)
                # await ws.send_str(msg.data + '->/answer')

        elif msg.type == aiohttp.WSMsgType.ERROR:
            print('ws connection closed with exception %s' % ws.exception())

    # 断开连接了
    print('websocket connection closed')
    return ws


app = web.Application()
app.add_routes([web.get('/', hello)])
app.add_routes([web.get('/ws', websocket_handler)])

web.run_app(app)


# 测试工具网站 http://www.websocket-test.com/
# ws://127.0.0.1:8080/ws?room=kuaile&user_name=sun
# ws://127.0.0.1:8080/ws?room=kuaile&user_name=tim
# ws://127.0.0.1:8080/ws?user_name=tim

# 如果想使用websocket 做推送的话,代码显然不能满足条件
# 我们都知道websocket 是双向通信,但是这个简单的聊天室,本质上也是接收到客户端信息,然后做出响应,并没有感觉到服务端是主动的。
# 使用ws 就可以主动的给客户端发送消息,我们可以单独起一个线程/线程,再利用队列等技术消息传递的特性,来主动给客户端发送消息。

# 比如本文要给全服务用户推送消息,就可以写单独起一个线程 thread,然后利用queue推送
# 伪代码
"""
# 线程的逻辑
q = queue()
while True:
    # 这里会阻塞,我们还可以用程序往这个q中放入推送的消息
    msg = q.get() 
    # 获得推送的消息后发送给全服,我们把全部的ws都存在两个pool中了,只需要遍历就习惯
    for ws in personal_pool:
        # 发送
        await ws.send_str(msg)
"""
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章