自学 python 中的异步编程 asyncio:实战(四)同时使用线程和协程的websocket

  • 本代码在上一个实战的基础上添加上了线程技能,开辟了一个线程,在线程中运行协程任务
  • 实现了简单的websocket的通信
  • 代码并不难,注释很详细,直接阅读即可
server端
  • server 会接收client发来的消息,并微微修改,我这里是末尾添加感叹号,然后发回给client
import asyncio
import threading
import time

import websockets


async def handler(websocket, path):  # 定义一个异步函数handler,用于处理websocket通信
    print(f"[{time.asctime()} connected!]")
    async for message in websocket:  # 使用async for循环接收客户端发送的消息
        print(f"[{time.asctime()} from client]: " + message)
        await websocket.send(message + "!")  # 将客户端发送的消息加上感叹号后返回给客户端


async def server_my():
    async with websockets.serve(handler, "127.0.0.1", 8765, ping_interval=200, ping_timeout=200,
                                timeout=2000):  # 使用websockets.serve函数创建一个websocket服务器,并指定handler函数作为处理函数
        print(f"[{time.asctime()} Server on]")
        await asyncio.Future()  # 等待异步任务完成


def loop_in_thread(new_loop):  # 定义一个函数loop_in_thread,用于在新线程中启动事件循环
    asyncio.set_event_loop(new_loop)  # 将新事件循环设置为当前线程的事件循环
    new_loop.create_task(server_my())  # 在新事件循环中创建一个任务,并将server_my函数作为任务的执行函数
    new_loop.run_forever()  # 启动新事件循环


def start():  # 定义一个函数start,用于启动websocket服务器和事件循环
    new_loop = asyncio.new_event_loop()  # 创建一个新的事件循环

    t = threading.Thread(target=loop_in_thread, kwargs={"new_loop": new_loop})  # 创建一个新线程,并将loop_in_thread函数作为线程的执行函数
    t.start()

    asyncio.run_coroutine_threadsafe(server_my(), new_loop)  # 在当前线程中启动server_my异步任务,并等待任务完成


if __name__ == '__main__':
    start()

client 端
  • client 我采用了两个协程任务,分别来处理发送和接收两个功能
import asyncio  # 引入asyncio模块,用于异步编程

import websockets  # 引入websockets模块,用于websocket通信


async def send(websocket):
    while True:
        message = input("请输入要发送的消息:")  # 获取用户输入的消息
        await websocket.send(message)  # 将用户输入的消息发送给服务器端
        await asyncio.sleep(1)  # 需要sleep才能保证其他协程任务能够运行,不然会阻塞接收消息的协程


async def receive(websocket):
    async for response in websocket:
        print(f"收到服务器端返回的消息:{response}")  # 打印服务器端返回的消息


async def main():
    async with websockets.connect("ws://localhost:8765") as websocket:  # 使用websockets.connect函数连接到服务器端
        await asyncio.gather(send(websocket), receive(websocket))  # 使用asyncio.gather函数同时运行send和receive协程


if __name__ == '__main__':
    asyncio.run(main())  # 启动事件循环并运行main协程

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值