asyncio数据流

asyncio.Streams 提供了与 socket 模块类似的编程模型,但所有操作都是非阻塞和异步的。

核心概念

asyncio 数据流主要涉及两个类:

  1. StreamReader: 用于从数据流中读取数据。

  2. StreamWriter: 用于向数据流中写入数据,并管理连接状态。

server端

复制代码
import asyncio

async def handle_client(reader: asyncio.StreamReader, writer: asyncio.StreamWriter):
    """
    这个协程在每个客户端连接时被调用。
    reader 和 writer 对象代表了与这个特定客户端的连接。
    """
    # 获取客户端的地址信息
    addr = writer.get_extra_info('peername')
    print(f"接收到来自 {addr} 的连接")

    try:
        while True:
            # 从客户端读取数据,最多读取 100 字节
            # read(n) 会一直等待,直到收到至少一个字节或连接关闭
            data = await reader.read(100)
            if not data:  # 如果收到空字节(b''),表示客户端关闭了连接
                break

            # 将收到的数据解码并打印
            message = data.decode('utf-8')
            print(f"从 {addr} 收到消息: {message!r}")

            # 准备回复
            response = f"服务器已收到你的消息:{message}"
            # 将回复写入数据流
            writer.write(response.encode('utf-8'))
            # 等待数据被发送(drain() 确保缓冲区数据被刷新到底层socket)
            await writer.drain()

        print(f"客户端 {addr} 断开连接")

    except ConnectionError as e:
        print(f"与 {addr} 的连接出现错误: {e}")
    finally:
        # 关闭连接
        writer.close()
        # 等待连接完全关闭
        await writer.wait_closed()
        print(f"与 {addr} 的连接已关闭")

async def main():
    # 启动服务器,绑定到本地回环地址(127.0.0.1)的 8888 端口
    server = await asyncio.start_server(
        handle_client,  # 客户端处理函数
        '127.0.0.1',    # 主机
        8888            # 端口
    )

    # 获取服务器监听的地址
    addrs = ', '.join(str(sock.getsockname()) for sock in server.sockets)
    print(f'服务器运行在 {addrs}')

    # 异步地永远运行服务器,直到被取消
    async with server:
        await server.serve_forever()

# 运行主函数
try:
    asyncio.run(main())
except KeyboardInterrupt:
    print("\n服务器被用户关闭")

client端

复制代码
import asyncio

async def tcp_echo_client(message):
    """
    一个简单的 TCP 回声客户端
    """
    # 建立到服务器的连接
    reader, writer = await asyncio.open_connection(
        '127.0.0.1',  # 服务器主机
        8888          # 服务器端口
    )

    print(f'发送: {message!r}')
    # 编码并发送消息
    writer.write(message.encode('utf-8'))
    # 确保数据被发送
    await writer.drain()

    # 等待服务器的回复(这里假设回复不超过 1KB)
    data = await reader.read(1024)
    print(f'收到: {data.decode("utf-8")!r}')

    # 告诉服务器我们不再发送数据(关闭写入端)
    writer.close()
    # 等待连接完全关闭
    await writer.wait_closed()
    print('连接已关闭')

async def main():
    # 发送一条消息
    await tcp_echo_client("Hello, World!")
    # 可以并发发送多条消息
    # await asyncio.gather(
    #     tcp_echo_client("Message 1"),
    #     tcp_echo_client("Message 2"),
    # )

# 运行客户端
asyncio.run(main())

关键方法和属性

StreamReader 的常用方法:
  • read(n) : 读取最多 n 个字节。如果流结束(EOF)则返回空字节。

  • readline() : 读取一行,以 b'\n' 结尾。非常适用于基于行的协议(如 HTTP 头、SMTP)。

  • readexactly(n) : 精确读取 n 个字节。如果连接在读取完 n 个字节前关闭,会引发 IncompleteReadError

  • readuntil(separator=b'\n'): 读取数据直到遇到指定的分隔符。分隔符也会被包含在返回的数据中。

StreamWriter 的常用方法:
  • write(data): 将数据写入底层的写缓冲区。此方法是非阻塞的。

  • writelines(data): 写入一个字节串或字符串的列表。

  • drain() : 非常重要! 等待缓冲区数据被发送到底层传输。在 write() 后调用它,以确保数据被真正发送出去。这是一个协程。

  • close(): 关闭连接。

  • wait_closed(): 等待连接完全关闭。这是一个协程。

  • get_extra_info(name) : 获取关于连接的额外信息,例如 'peername'(客户端地址)、'sockname'(服务器地址)等。

参照 https://docs.python.org/zh-cn/3.10/library/asyncio-stream.html#get-http-headers

相关推荐
Cherry Zack20 分钟前
FastAPI 入门指南 :基础概念与核心特性
开发语言·python·fastapi·1024程序员节
言德斐41 分钟前
Python Web框架深度对比:Django vs Flask vs FastAPI(含优缺点与选型策略)
前端·python·django
开心-开心急了1 小时前
Flask入门教程——李辉 第5章: 数据库 关键知识梳理
笔记·后端·python·flask·1024程序员节
CodeCraft Studio2 小时前
国产化Excel开发组件Spire.XLS教程:在Python中将Pandas DataFrame导出到Excel的详细教程
python·excel·pandas
B站_计算机毕业设计之家3 小时前
python舆情分析可视化系统 情感分析 微博 爬虫 scrapy爬虫技术 朴素贝叶斯分类算法大数据 计算机✅
大数据·爬虫·python·scrapy·数据分析·1024程序员节·舆情分析
B站_计算机毕业设计之家3 小时前
基于python人脸识别系统 人脸检测 实时检测 深度学习 Dlib库 ResNet深度卷积神经网络 pyqt设计 大数据(源码)✅
python·深度学习·目标检测·计算机视觉·信息可视化·人脸识别·1024程序员节
汤姆yu3 小时前
2026版基于python大数据的电影分析可视化系统
大数据·python·1024程序员节·电影分析可视化
Pa2sw0rd丶3 小时前
Python 循环导入详解:为什么会导致生产环境崩溃及企业级解决方案
后端·python
梨轻巧3 小时前
Maya Python入门:创建locator、getAttr() 获取属性、setAttr() 设置属性、定位xform()
python·maya
Xxxx. .Xxxx4 小时前
Classwork 5 - Check the HTML Tags
python