【python】asyncio异步socket通信 | asyncio streams编写TCP通信 | asyncio.StreamReader读取长串数据

一、asyncio异步通信

学习博客/文档归类一下放在下面:

官方文档

简单易懂的例子+各个函数详解:Python 使用asyncio tcp
协程等概念解释+github实例:python 异步socket编程
官方文档翻译:asyncio异步IO——Streams详解
详细函数解释:Python asyncio 异步编程(三)

二、解决asyncio.StreamReader读取长串数据

StreamReader一些内部函数功能博主翻译/理解

最近用asyncio做了异步socket tcp通信,在使用asyncio.StreamReader对象读取数据时出现了一点问题。
首先一些基本代码都是学习网上的,客户端代码:

 reader, writer = await asyncio.open_connection(
        '127.0.0.1', 8888)

但我发现如果服务端给客户端发的信息过长,reader.read()函数就不起作用,虽然官网对这个函数的解释是参数什么都不写就会读取所有的数据。网络查了一下也只发现一个解决办法(图中他其实遇到了跟我一样的问题也就是一调用reader.read()就会永久阻塞,并不会返回什么接收到的数据):
在这里插入图片描述
但是我一用yield就出错
后来想了想干脆用at_eof()这个函数吧,但怎么打印它都返回False也就缓冲区不为空。看官方文档对这个函数的解释:

如果缓冲区为空并且 feed_eof() 被调用,则返回 True 。

查了半天也没找到feed_eof()这个函数到底干什么用,但在at_eof()之前调用一下就解决一切问题了。

官网解释:
feed_eof()
Acknowledge the EOF.

具体代码:(但并没有解决根本原因,第一次对方发送消息可以正常接收,但之后发送消息就会报错feed_data after feed_eof的错)

async def recv_msg(self):
	while True:
		data = bytearray()
		while True:
			chunk = await self.reader.read(100)
			if not chunk:
				break
			data += chunk
			
			self.reader.feed_eof()
			if self.reader.at_eof():
				print(data)	#这里就是一个完整的接收数据了

这么一看if not chunk好像也能直接判断缓冲区是不是空的。。。。并且发现await self.reader.read(100)好像不会因为对方没发送数据它就一直阻塞,而是会一直读取一直读取。那await这个功能意义何在?
feed_of()这个函数的发现权当我减少运用了一次await self.reader.read(100)

上述问题的出现我归结于用了feed_eof()这个函数,我现在还不懂这个函数的作用。但不使用它之前我可以确定的是:

  • at_eof()永远返回False

  • await self.reader.read(100)会在对方没有发消息的时候一直阻塞,而不是不断返回None或之类
    所以之后我还是改用self.reader.read(100)这种低级的方法了,只能将参数改大,保证大于对方会发送的最长消息的字节数。如果以后需要传输文件的话就麻烦了需要再想想办法。但其实还有一个弱智办法是让对方先把文件大小传输过来,我再动态改变参数,应该是可行的。
    上述方法又产生一个问题,如果参数设置过大,对方发送信息又过快,接收消息会产生TCP粘包的情况,再找一个解决方法就是使用await self.reader.readuntil(seperator = b"\xFF\xFF"),让发送方在每条发送数据包的后面都加上这个seperator,亲测有效解决问题。

三、一些想整理的

客户端判断是否还有在连接服务器,可以用writer.is_closing(),把writer设为类的属性,这样在不同的async函数里都可以获取,以控制reader函数,或者说整个的循环连接服务器的函数得以在连接断了之后,或是直接退出函数执行,或是开始不断连接服务器

writer函数肯定是放在一个循环中不断写入消息的,这个循环一定要写个asyncio.sleep(),以时不时的暂停一下,不然有可能会陷入死循环。

reader函数则不用asyncio.sleep(),它的await self.reader.readuntil(...)会在消息来的时候才执行,不然就停滞在这里并把执行权力让给其他协程。

客户端/服务器的例子,完整的代码

<p><strong><span style="color: #ff0000;">无论是micropython还是python3.5+,都有async/await/asyncio。</span></strong></p> <p><strong><span style="color: #ff0000;">本教程不会去深入讲解异步底层的实现。</span></strong></p> <p><strong><span style="color: #ff0000;">但会通过数个实例来简单讲解如何使用async/await/asyncio,让大家快速了解异步编程。</span></strong></p> <p><strong><span style="color: #ff0000;">本教程所使用的python版本为python3.7。</span></strong><strong><span style="color: #ff0000;">部分内容属于之前课程的延伸。</span></strong></p> <p><strong><span style="color: #ff0000;">*重要提醒: 不要在毫无基础下学习本教程,不然你会一头雾水。可以在学习完我micropython教程后有兴趣再来学习该教程。本教程是micropython学员需求才制作,非面向零基础。</span></strong></p> <p><strong><span style="color: #ff0000;"> </span></strong></p> <p><strong><span style="font-size: 12px;">在学习本教程<span style="color: #ff0000;">之前</span>你需要掌握:</span></strong></p> <p><strong><span style="font-size: 12px;">1: python3基础(变量,循环,函数,常用库,常用方法)。</span></strong></p> <p> </p> <p><span style="color: #ff0000;"><strong>--list:</strong></span></p> <p><strong><span style="font-size: 12px;"><strong>    </strong>    1.1 认识异步与本教程</span></strong></p> <p><strong><span style="font-size: 12px;"> <strong>    </strong>   2.1 了解http与socks5协议</span></strong></p> <p><strong><span style="font-size: 12px;"><strong>    </strong>    2.2 根据socks5协议编写代码</span></strong></p> <p><strong><span style="font-size: 12px;"><strong>    </strong>    2.3 编写异步程序,分析async/await执行逻辑</span></strong></p> <p><strong><span style="font-size: 12px;"><strong>    </strong>    2.4 asyncio socks5转发服务器</span></strong></p> <p><strong><span style="font-size: 12px;"> <strong>    </strong>   3.1 websocket协议</span></strong></p> <p><strong><span style="font-size: 12px;"> <strong>    </strong>   3.2 根据websocket协议编写代码(处理头)</span></strong></p> <p><strong><span style="font-size: 12px;"><strong>    </strong>    3.3 根据websocket协议编写代码(处理帧)</span></strong></p> <p><strong><span style="font-size: 12px;">   <strong>    </strong> 3.4 asyncio websocket服务器</span></strong></p> <p><strong><span style="font-size: 12px;"> <strong>    </strong>   4.1 uwsgi+redis+websocket网页多人聊天室(异步) </span></strong></p> <p><strong><span style="font-size: 12px;">        5.1 asyncio wait_gather_result</span></strong></p> <p><strong><span style="font-size: 12px;"> <strong>    </strong>   5.2 总结与介绍更多成品异步库</span></strong></p>
评论 2 您还未登录,请先 登录 后发表或查看评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:精致技术 设计师:CSDN官方博客 返回首页

打赏作者

IVever_KB

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值