多路复用(select、epoll)实现tcp服务
-------------------------------多路复用的服务器(select)-------------------------------
网络通信被Unix系统抽象为文件的读写,通常是一个设备,由设备驱动程序提供,驱动可以知道自身的数据是否可用。支持阻塞操作的设备驱动通常会实现一组自身的等待队列,如读/写等待队列用于支持上层(用户层)所需的block或non-block操作。设备的文件的资源如果可用(可读或者可写)则会通知进程,反之则会让进程睡眠,等到数据到来可用的时候,再唤醒进程。这些设备的文件描述符被放在一个数组中,然后select调用的时候遍历这个数组,如果对于的文件描述符可读则会返回改文件描述符。当遍历结束之后,如果仍然没有一个可用设备文件描述符,select让用户进程则会睡眠,直到等待资源可用的时候在唤醒,遍历之前那个监视的数组。每次遍历都是依次进行判断的。
缺点:
select的一个缺点在于单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024,可以通过修改宏定义甚至重新编译内核的方式提升这一限制,但是这样也会造成效率的降低。一般来说这个数目和系统内存关系很大,具体数目可以cat /proc/sys/fs/file-max察看。32位机默认是1024个。64位机默认是2048.对socket进行扫描时是依次扫描的,即采用轮询的方法,效率较低。当套接字比较多的时候,每次select()都要通过遍历FD_SETSIZE个Socket来完成调度,不管哪个Socket是活跃的,都遍历一遍。这会浪费很多CPU时间。
应用:
#import select:对应import包的引用操作
#readable,writeable,exceptinal=select.select(inputs,[],[]):使用select对套接字组成的列表进行遍历,过滤出对应的未堵塞的套接字
python代码示例:
#coding=utf-8 #引用对应的包
from socket import * import select import sys #函数:main
def main():
#创建套接字
serTcpSocket=socket(AF_INET,SOCK_STREAM) #绑定端口和ip,sys.argv[1] 运行时传递的参数
serTcpSocket.bind(("",int(sys.argv[1]))) #打开被动监听
serTcpSocket.listen(5) print("-----服务器开启-----") #创建列表,存储对应的套接字
inputs=[serTcpSocket] #循环
while True:
#使用select进行对应套接字的处理过滤
readList,writeList,exceptList=select.select(inputs,[],[]) #遍历readList列表进行操作
for sockItem in readList:
#如果为服务器套接字,进行accept()数据的接收
if sockItem==serTcpSocket:
#监听接受客户端传递过来的数据信息
newSocket,destAddr=sockItem.accept() print("客户端(%s)以上线"%str(destAddr)) #将用于与客户端通信的套接字进行存储
inputs.append(newSocket) else:
#进行客户端发送过来的数据的接收
recvData=sockItem.recv(1024) #进行判断,如果传递过来的数据不为空
if len(recvData)>0:
#进行客户端发送过来的数据的打印操作
print("客户端(%s):%s"%(str(destAddr),recvData))
else:
#表示客户端下线
print("客户端(%s)以下线!"%str(destAddr)) #进行对应该客户端套接字的关闭操作
sockItem.close() #将该套接字从对应的列表中移除
inputs.remove(sockItem) #程序入口
if __name__=="__main__":
main()
select多路复用实现tcp服务
-------------------------------多路复用的服务器(epoll)-------------------------------
优点:
1、没有最大并发连接的限制,能打开的FD的上限远大于1024
2、效率提升,不是轮询的方式,不会随着FD数目的增加效率下降。只有活跃可用的FD才会调用callback函数;即epoll最大的优点就在于它只管你“活跃”的连接,而跟连接总数无关,因此在实际的网络环境中,epoll的效率就会远远高于select。
应用:
#import select:引用select包
#epoll=select.epoll():创建epoll对象
#soc.fileno():获取套接字对应的文件描述符
#epoll.register(soc.fileno(),select.EPOLLIN|select.EPOLLET):将创建的套接字添加到epoll的事件监听
EPOLLIN (可读)
EPOLLOUT (可写)
EPOLLET (ET模式)
epoll对文件描述符的操作有两种模式:LT(level trigger)和ET(edge trigger)。LT模式是默认模式,LT模式与ET模式的区别如下:
LT模式:当epoll检测到描述符事件发生并将此事件通知应用程序,应用程序可以不立即处理该事件。下次调用epoll时,会再次响应应用程序并通知此事件。
ET模式:当epoll检测到描述符事件发生并将此事件通知应用程序,应用程序必须立即处理该事件。如果不处理,下次调用epoll时,不会再次响应应用程序并通知此事件。
#epollList=epoll.poll():进行已注册套接字的扫描操作
#epoll.unregister(soc.fileno()):从epoll对象中注销该套接字
#coding=utf-8 #引用对应的包
from socket import * import select import sys #函数:main
def main():
#创建服务器的套接字
serTcpSocket=socket(AF_INET,SOCK_STREAM) #进行端口和ip的绑定操作
serTcpSocket.bind(("",int(sys.argv[1]))) #开启被动,进行监听
serTcpSocket.listen(10) #创建一个epoll对象
epoll=select.epoll() #使用epoll对套接字在操作系统中进行注册
epoll.register(serTcpSocket.fileno(),select.EPOLLIN|select.EPOLLET) #创建两个字典
#根据套接字的文件标识符对应套接字
connection={} #根据套接字的文件标识符对应ip和端口元组信息
address={} #提示服务开启
print("------服务开启-----") #进行循环遍历
while True:
#接收对象中,未阻塞的套接字
epollList = epoll.poll() for fd,event in epollList:
#判断是否为服务器的套接字
if fd==serTcpSocket.fileno():
#接收客户端传递过来的数据信息
newSocket,destAddr=serTcpSocket.accept() print("客户端(%s)以上线"%str(destAddr)) #将对应的数据向字典中进行存储
connection[newSocket.fileno()]=newSocket
address[newSocket.fileno()]=destAddr #将套接字在对应的epoll对象中进行注册
epoll.register(newSocket.fileno(),select.EPOLLIN|select.EPOLLET) elif event==select.EPOLLIN:
#在字典中取出对应的套接字对象和地址(ip和端口)
soc=connection[fd]
addr=address[fd] #接收客户端发送过来的数据信息
recvData=soc.recv(1024) #判断客户端是否下线
if len(recvData)>0:
#进行打印
print("客户端(%s):%s"%(str(addr),recvData)) #echo服务,将信息回发到客户端
soc.send(recvData)
else:
print("客户端(%s)以下线"%str(addr)) #进行该套接字在epoll中的注销操作
epoll.unregister(fd) #关闭该套接字
soc.close() #程序入口
if __name__=="__main__":
main()
多路复用epoll实现tcp服务
多路复用(select、epoll)实现tcp服务的更多相关文章
- linux网络编程 IO多路复用 select epoll
本文以我的小型聊天室为例,对于服务器端的代码,做了三次改进,我将分别介绍阻塞式IO,select,epoll . 一:阻塞式IO 对于聊天室这种程序,我们最容易想到的是在服务器端accept之后,然后 ...
- IO多路复用(二) -- select、poll、epoll实现TCP反射程序
接着上文IO多路复用(一)-- Select.Poll.Epoll,接下来将演示一个TCP回射程序,源代码来自于该博文https://www.cnblogs.com/Anker/p/3258674.h ...
- 利用select实现IO多路复用TCP服务端
一.相关函数 1. int select(int maxfdp, fd_set *readset, fd_set *writeset, fd_set *exceptset,struct timeva ...
- I/O模型系列之五:IO多路复用 select、poll、epoll
IO多路复用之select.poll.epoll IO多路复用:通过一种机制,一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作. 应用:适用于针 ...
- Linux 网络编程的5种IO模型:多路复用(select/poll/epoll)
Linux 网络编程的5种IO模型:多路复用(select/poll/epoll) 背景 我们在上一讲 Linux 网络编程的5种IO模型:阻塞IO与非阻塞IO中,对于其中的 阻塞/非阻塞IO 进行了 ...
- 网络编程socket 结合IO多路复用select; epool机制分别实现单线程并发TCP服务器
select版-TCP服务器 1. select 原理 在多路复用的模型中,比较常用的有select模型和epoll模型.这两个都是系统接口,由操作系统提供.当然,Python的select模块进行了 ...
- 04: 事件驱动、五种I/O操作、I/O多路复用select和epoll
网络编程其他篇 目录: 1.1 事件驱动 1.2 五种I/O操作 1.3 I/O 多路复用之select.poll.epoll详解 1.1 事件驱动返回顶部 1.什么是事件驱动 定义:就是根据不同事 ...
- I/O多路复用select/poll/epoll
前言 早期操作系统通常将进程中可创建的线程数限制在一个较低的阈值,大约几百个.因此, 操作系统会提供一些高效的方法来实现多路IO,例如Unix的select和poll.现代操作系统中,线程数已经得到了 ...
- 转一贴,今天实在写累了,也看累了--【Python异步非阻塞IO多路复用Select/Poll/Epoll使用】
下面这篇,原理理解了, 再结合 这一周来的心得体会,整个框架就差不多了... http://www.haiyun.me/archives/1056.html 有许多封装好的异步非阻塞IO多路复用框架, ...
随机推荐
- 动态rem与1px边框问题的理解
当我们在项目开发中,拿到设计师的设计图,满怀欣喜的准备按照设计图将页面实现出来的时候,我们通常会遇到这个问题: 如何将页面的内容按照在不同手机屏幕浏览的情况下,比例都是不变的呢?这个时候我们就需要使用 ...
- 6步就能搞出个react网站哈,玩一把!
1.安装mk-tools命令行工具 $ npm i -g mk-tools 2.创建空website $ mk website myDemo $ cd myDemo 3.clone应 ...
- 笔记本电脑连接上WiFi后,弹不出登录界面怎么办?
以CMCC为例子 步骤: 1 连接成功CMCC之后,打开适配器设置.右击无线网卡,选择属性 2.双击INTERNET协议版本4 3.将DNS改成自动获取,然后确定 4.再确定 5.然后重新断开CMCC ...
- TASKCTL敏捷调度理念的诠释
功能完整是基本,简单易用才是王道,这就是TASKCTL对敏捷的朴素定义.功能少,怎么复杂也会简单:而功能体系完整,怎么简单也会复杂.因此,简单与复杂是相对的,而TASKCTL正是追求那种在功能完整不可 ...
- mybatis中的mapper接口文件以及example类的实例函数以及详解
##Example example = new ##Example(); example.setOrderByClause("字段名 ASC"); //升序排列,desc为降序排列 ...
- 2.ssh密钥登陆(ssh无密码登陆)
1.A主机生成密钥对 ssh-keygen -t rsa 2.将A主机的公钥发给B主机 scp id_rsa.pub linux2:/cloud ...
- 关于IE,Chrome,Firefox浏览器的字符串拼接问题
昨天项目测试的时候,IE8.IE11测试勾选checkbox然后执行保存的时候,竟然执行的结果与预期相反,吓屎我了,最终排查之下,原来是拼接checkbox的值的时候出现的问题.本人对js了解知之甚少 ...
- session和cookie的辨析[阅读]
session和cookie是网站浏览中较为常见的两个概念,也是比较难以辨析的两个概念,但它们在点击流及基于用户浏览行为的网站分析中却相当关键.基于网上一些文章和资料的参阅,及作者个人的应用体会,对这 ...
- GO中的数组切片
GO中的数组切片可以看做是功能更强大的数组,在append数据时,可以自动调整内存大小以适应数据实际大小,有些类似于C#中的List<T>. GO 中数组切片的“容量”与实际储存的大小可以 ...
- 自定义组件-BreadcrumbTreeView 的使用
一.问题概述 树形结构是开发中常用的一种组织数据的结构,不少平台也提供了对应的控件.而在android平台中,出于使用手指操作树形结构不是很方便的原因,并没有提供树形结构控件.但在实际应用中,不可避免 ...