多路复用(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多路复用框架, ...
随机推荐
- 【Apache】 VirtualHost配置
主要配置两点: 1)配置vhost ,可单独建文件,也可直接在http.conf添加内容 如果单独建文件,查看http.conf 中Include 配置文件的路径,并在对应路径新建http_vhost ...
- TransactionTemplate编程式事务管理方式的进阶使用---自定义拓展模板类
1, 前面一篇的文章介绍了TransactionTemplate的基本使用方法. 同事在其基础上又做了一层封装,这样更贴合本公司的业务与规范. 2, 首先定义了两个接口: ServiceTemplat ...
- Android Binder机制详解:手写IPC通信
想要掌握一样东西,最好的方式就是阅读理解它的源码.想要掌握Android Binder,最好的方式就是写一个AIDL文件,然后查看其生成的代码.本文的思路也是来自于此. 简介 Binder是Andro ...
- java_final修饰符
1.修饰变量时,表示该变量一旦获得初始值就不可改变 final修饰的成员变量必须由程序员显示地指定初始值,系统不会进行隐式初始化 类变量:必须在初始化块中指定初始值或声明该类变量时指定初始值 实例变量 ...
- akoj-1076-Encoding
Encoding Time Limit:1000MS Memory Limit:65536K Total Submit:62 Accepted:35 Description Given a stri ...
- 纯Css绘制三角形箭头三种方法
在制作网页的过程中少不了绘制类似图片的三角形箭头效果,虽然工程量不大,但是确实麻烦.在学习的过程中,总结了以下三种方法,以及相关的例子. 一.三种绘制三角形箭头方法 1.方法一:利用overflow: ...
- 605. Can Place Flowers种花问题【leetcode】
Suppose you have a long flowerbed in which some of the plots are planted and some are not. However, ...
- 在App Store中无法更新xcode 8.3.2时 以及更新新系统10.12
今天更新Xcode 遇到三个坑坑1 要想更新Xcode最新版本 需要先把电脑系统更新到10.12 坑2 电脑系统更新到10.12 需要更新Mac Sierra 就可以了坑3 在App Store中下载 ...
- BOM部分笔记整理
BOM部分整理 (章节 8.9) 概览: 一.介绍BOM 在web中,JS的核心对象就是BOM. 1.1 在浏览器中,window对象 == global 所以,你在全局环境下定义的变量,函数都会自动 ...
- bootstrap 切换页签失效的解决方法
概述 bootstrap开发标签页时,标签页显示正常,但点击时候对应内容区域没有变化. 具体症状与解决方案 1.标签页UI出现,但点击无反应,标签页UI并未随点击进行切换 先检查bootstrap.c ...