1. 结语
异步网络编程实际上是一个很古老很底层的东西.核心思想也很朴素.总的来说虽然其性能优异消耗小, 但限制大写法不直观,对编程人员并不友好.因此在很多语言中都将并发交给多线程来执行从而提高对编程的友好程度. python中有丰富的多进程多线程接口,可以相当轻易的实现并发.但随着对性能的要求越来越高,异步编程重新被捡起来.
1.1. python异步网络编程的发展
异步网络编程的主要代表就是javascript.js由于其本身没有多线程.因此只能依靠异步回调来实现并发.这原本是劣势, 但由于node.js的兴起,异步网络编程的性能优势再次被人们发现,node.js在高并发的同时可以保持极低的内存消耗和cpu消耗, 虽然要用到多核也必须依赖多进程,但总体来说依然很具优势.前几年一度有node.js成为后端最优解决方案,javascript统一网络编程的趋势.
当然这中风潮只是昙花一现,但这确实为许多其他编程语言提了醒.go语言专为协程提供特殊语法在使用,当然它的所谓协程并不是一般意义上的协程,而是更加接近线程的的东西,因为其调度器十分强大而且对多核有更好的支持,所以性能更加强大.
而python早在很久以前就已经有协程工具,gevent,greenlet,eventlet都是其中的代表,但他们往往是通过monkeypatch的方式替换python标准库的线程实现协程.而python的另一个实现pypy直接将协程eventlet加入了标准库.他们同样性能优异,唯一的缺点就是语义不明确而且库生态混乱.
我们都知道python这门语言的设计思路就是希望实现功能可以只用一种最优的方法(似乎有点洁癖),而协程作为一种语言特性由第三方库实现确实有点难看.因此在这么久的混乱之后Cpython中加入了专门的协程语法和标准库接口,旨在统一协程方面的规范.
异步编程主要有两种实现
回调函数这是性能最好的实现方式,js基本就是靠回调.
好处是原理简单没有额外消耗,但坏处就是所谓的回调地狱,像python又没有js那样方便的匿名函数, 这让回调函数成了不是那么优雅的一种方式.
async await
语法,允许执行程序保存栈状态并可以在多个执行栈中跳转,有点类似python中的生成器.这套语法是C#中设计并完善的,python的协程语法这也是参考自其中,而目前python的协程实现也是使用生成器. 这种实现的优点是语法相对没那么反人类,而且语义更加明确,缺点是协程语法具有倾入性.
1.2. 关于使用TCP还是UDP
下面是总结的TCP和UDP协议的不同之处.但说这么多,还是要说,能用tcp不要用udp.
TCP是面向流字符的,数据流间无边界;UDP是面向分组的,分组间有明确的边界.对于TCP,发送一串数字(1,2,3,4,5),接收时有可能变成两次(1,2)和(2,4,5),或者变成任意接收方式,协议栈只保证接收顺序正确;UDP发送一个分组,接收方或者接收完全失败,如果成功整个分组都会接收到.
TCP是面向连接的,UDP是无连接的.类比于打电话和发电报的关系.TCP建立一个连接需要3次握手IP数据包,断开连接需要4次握手.另外断开连接时发起方可能进入TIME_WAIT状态长达数分钟(视系统设置,windows一般为120秒),在此状态下连接(端口)无法被释放.
TCP保证通讯的可靠,通过数据校验保证发送和接收到的数据是一致的;UDP是不可靠的,发送一串数字分组(1,2,3)可能接收到时就变成(1,0,0)了,做UDP连接时需要自己做数据校验.
TCP数据是有序的,以什么顺序发送的数据,接收时同样会按照此顺序;UDP是无序的,发出(1,2,3),有可能按照(1,3,2)的顺序收到.应用程序必须自己做分组排序.
TCP因为建立连接,释放连接,IP分组校验排序等需要额外工作,速度较UDP慢许多.TCP适合传输数据,UDP适合流媒体.
UDP比TCP更容易穿越路由器防火墙.
1.3. 相关的扩展和模块
http协议相关:
- sanic 一个使用协程的类flask的http服务器框架
- aiohttp 提供http客户端和服务器框架实现
- python-socketio 提供异步接口的socketio客户端工具
还没有评论,来说两句吧...