基础入门_Python-网络编程.分分钟掌握阻塞/非阻塞/同步/异步IO模型?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基础入门_Python-网络编程.分分钟掌握阻塞/非阻塞/同步/异步IO模型?相关的知识,希望对你有一定的参考价值。
概念梳理:
故事独白: 满满爱喝茶,废话不多说,开始煮开水.
出场人物: 满满, 普通水壶, 高级水壶(水开会响)
1. 满满把水壶放在火上, 站在那里等水开(同步阻塞)
满满觉得自己有点儿傻逼~
2. 满满把水壶放在火上,去客厅看电视,时不时的去厨房瞅瞅水开木有(同步非阻塞)
满满觉得自己还是有点傻~,于是买了个高级水壶, 水开后会响~
3. 满满把高级水壶放在火上, 站在那里等水开(异步阻塞)
满满想高级水壶水开会自己叫~为毛不去看个电视哪?
4. 满满把高级水壶放在火上, 去客厅看电视, 水壶响之前不再去看了, 响了再去拿水壶(异步非阻塞)
满满突然觉得自己很聪明~
总结: 通过一个小故事详细描述了同步阻塞/同步非阻塞/异步阻塞/异步非阻塞的场景,最后说一点阻塞/非阻塞是相对于满满来说的,而同步/异步是相对于水壶来说的,所以前者更偏向于程序自己本身,而后者更偏向于消息通知机制
常见模型:
说明: 网络I/O的本质是SOCKET读取,SOCKET在Linux系统下被抽象为流,I/O其实就是对流的操作,但是操作又分为两个阶段:等待流数据准备阶段和从内核向进程复制数据阶段,其实整个过程是网络上的数据到达时被复制到内核缓冲区,然后把数据从内核缓冲区复制到用户空间应用进程缓冲区
同步 阻塞I/O
说明: 应用程序调用一个IO函数,导致应用程序阻塞,直到数据被准备好并且复制到用户空间进程缓冲区,IO函数才返回成功指示,常常会遇到输入操作(recv/recvfrom)在缓冲区中没有数据可读时,则调用线程在数据到来之前会一直被休眠,输出操作(send/sendto)在缓冲区没有可用空间时线程会一直被休眠,接受连接(accept)在没有连接请求时线程一直被休眠,外出连接(connect)在收到服务器响应前线程一直被休眠
问题: 使用阻塞套接字开发网络程序比较简单,适合希望能够理解发送接受数据且处理少量套接字的场景,当希望同时处理大量套接字时将无从下手~
同步 非阻塞I/O
说明: 应用程序反复调用IO函数,并马上返回错误,内核数据没准备好之前,不让线程睡眠,而让函数立即返回错误,所以数据没准备好之前线程处于非阻塞,但是从数据准备好那一刻开始线程就处于阻塞状态直到数据拷贝完成返回
问题: 使用非阻塞套接字,在数据的收发量不均,时间不定时的场景确实有优势,但由于会定期轮询检查内核数据是否准备好,非常浪费系统资源,而且需要对内核错误合理处理
同步多路复用I/O
说明: 应用程序通过基于内核级别的select/poll在多个阻塞套接字上监听内核数据是否准备就绪,其中任何一个套接字数据准备就绪就返回,然后进程调用recvfrom系统调用将数据从内核缓冲区拷贝到用户空间应用程序缓冲区,多说一句在数据拷贝过程中是阻塞状态的
异步 I/O
说明: 应用程序调用后不能立即得到结果,实际处理这个调用的部件在完成后,通过状态,通知和回调来通知调用者结果,整个过程包括等待数据及拷贝数据都是非阻塞的
扩展知识:
1. select本质是通过检查fd标志位的数据结构来判断fd对应的内核数据是否准备就绪,默认的fd存储方式导致单个进程可监视的fd数量有限制,且能监听的端口大小也有限制,一般和内存关闭比较大/proc/sys/fs/file-max,而且对fd扫描是线型扫描,不管是否有数据都扫描,浪费CPU时间,poll和select类似,但由于以链表存储fd所以没有最大连接数的限制.但它们有一个共同缺点,大量的fd数据结构被重复的传递与用户空间与内核空间.
2. epoll从本质上解决了select无谓的线型扫描,只会告诉数据已准备就绪的fd,而且基本没有最大并发连接的限制(1G内存能监听10万个端口),而且内存拷贝使用mmap减少复制开销
本文出自 “ζ自动化运维开发之路ζ” 博客,请务必保留此出处http://xmdevops.blog.51cto.com/11144840/1861280
以上是关于基础入门_Python-网络编程.分分钟掌握阻塞/非阻塞/同步/异步IO模型?的主要内容,如果未能解决你的问题,请参考以下文章
10个python入门小游戏,零基础打通关,就能掌握编程基础
Python基础教程(入门教程),30分钟玩转Python编程!
不会吧不会吧,不会有人真的三分钟入门Python了吧?Python编程基础