asyncio-流

流Stream是处理网络连接的async/await的高层级原语。流允许发送和接收数据,而不需要使用回调或低级协议传输。

Stream函数

  1. coroutine asyncio.open_connection(host=None,port=None, *,limit=None, ssl=None, family=0, proto=0,flags=0,sock=None, local_addr=None, server_hostname=None, ssl_handshake_timeout=None,happy_eyeballs_delay=None,interleave=None)
    • 建立连接并返回一对(reader, writer)对象,返回的reader和writer对象是StreamReader和StreamWriter类的实例。
    • limit是StreamReader实例使用的缓冲区大小,默认64kb。
    • 其他参数传递给loop.create_connection()
    • 3.10删除了loop形参
  2. coroutine asyncio.start_server(clinet_connected_cb, host=None, port=None, *, limit=None)
    • 启动套接字服务,当一个新的客户端连接被建立时,回调函数client_connected_cb被调用。该函数会接收一对(reader,writer)参数。
    • clinet_connected_cb是一个普通的可调用对象或协程函数,如果是协程函数会被自动作为Task调度
    • 3.10删除了loop形参

Unix套接字

  1. coroutine asyncio.open_unix_connection(path=None, *, limit=None, ssl=None, sock=None, server_host_name=None, ssl_handshake_timeout=None)
    • 与open_connection类似,但是是在Unix套接字上的操作。建立一个Unix套接字连接并返回(reader,writer)
  2. coroutine asyncio.start_unix_server(client_connected_cb, path=None, *, limit=None, sock=None, backlog=100, ssl=None, ssl_handshake_timeout=None, start_serving=True)
    • 与start_server类似,但是在Unix上

StreamReader

class asyncio.StreamReader
- 该类表示一个读取器对象,一般不直接实例化StreamReader对象,应使用open_connection()和start_server()

  1. coroutine read(n=-1):
    • 读取n个byte数据,如果n为-1,则读取到EOF并返回所有读取到的byte,如果读到EOF且内部缓冲区为空,则返回一个bytes对象
  2. coroutine readline()
    • 读取一行,即读取\n结尾的字节序列
    • 如果到了EOF则返回EOF前的数据
  3. coroutine readexactly(n):
    • 精确读取n个bytes,不会超过也不能少于,如果读完n个byte之前读取到EOF,则引发IncompleteReadError,使用IncompleteReadError.partial属性来获取到达流结束之前读取的bytes字符串。
  4. coroutine readuntil(separator=b'\b')
    • 读取到separator,数据和separator都会在返回的数据中。
    • 如果超过了缓存限制,则引发LimitOverrunError异常,数据将留在内部缓存区并可以再次读取
    • 如果先遇到EOF则会引发IncompleteReadError异常,并重置内部缓冲区。

StreamWriter

class asyncio.StreamWriter
- 写入器对象

  1. write(data)
    • 尝试立即将data写入到下层的套接字,如果写入失败会被排入内部写缓冲队列直到可以被发送。应该和drain方法一起使用
  2. writelines(data)
stream.write(data)
await stream.drain()
  1. close():关闭流以及下层套接字,此方法应该和wait_colsed()一起使用
stream.close()
await stream.wait_closed()
  1. can_write_eof():如果下层传输支持write_eof()方法则返回True,否则返回False
  2. write_eof():在已缓冲的写入数据被刷新后关闭流的写入端
  3. transport: 返回下层的asyncio传输
  4. coroutine drain() : 等到直到可以适当的恢复写入流
    • 当下层缓冲区满,drain会阻塞直到缓冲区大小减小到最小以便恢复写入,当没有要等待的数据时,drain会立即返回
  5. is_closing(): 如果流被关闭返回True
  6. coroutine wait_closed(): 等待直到流被关闭
  7. get_extra_info(name, default=None):访问可选的传输信息
# server
import asyncio


async def handle_echo(reader, writer):
    while 1:
        data = await reader.read(100)
        message=data.decode()
        addr = writer.get_extra_info("peername")
        print(f"received{message!r} from {addr!r}")
        print(f"send:{message!r}")
        data = await asyncio.to_thread(input)
        
        writer.write(bytes(data, 'utf-8'))
        await writer.drain()
        if data=='quit':
            print("close the connection")
            break 
        
    writer.close()
    await writer.wait_closed()

async def main():
    server = await asyncio.start_server(handle_echo, 'localhost', 8888)
    addrs = ','.join(str(sock.getsockname()) for sock in server.sockets)
    print(f"serving on {addrs}")
    async with server:
        await server.serve_forever()

asyncio.run(main())

# client
import asyncio 

async def tcp_echo_clent():
    reader, writer = await asyncio.open_connection('localhost', 8888)
    while True:
        message = input()
        print(f"send:{message!r}")
        writer.write(message.encode('utf-8'))
        await writer.drain()
        data = await reader.read(100)
        print(f"received:{data.decode()!r}")
        
        if data.decode()=='quit':
            print("close the connection")
            break

    writer.close()
    await writer.wait_closed()
asyncio.run(tcp_echo_clent())


posted @   店里最会撒谎白玉汤  阅读(89)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示