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)
"""
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章