博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
IO多路复用
阅读量:4671 次
发布时间:2019-06-09

本文共 2048 字,大约阅读时间需要 6 分钟。

在前一篇文章中,我们实现了通过非阻塞套接字的并发服务,但是这种实现方式是有很多问题的。

一、CPU资源的极大浪费;

二、如果没有连接那么,accept()和recv()都在做无用功;

三、对BlockIOError的处理也是在做无用功。

针对以上问题,现在我们使用IO多路复用的技术来实现并发的服务。

什么是IO多路复用

IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程。IO多路复用适用如下场合:

1.当客户需要处理多个描述符时,必须使用I/O复用。2.当一个客户同时处理多个套接口时,而这种情况是可能的,但很少出现。3.如果一个TCP服务器既要处理监听套接口,又要处理已连接套接口。4.如果一个服务器即要处理TCP,又要处理UDP。5.如果一个服务器要处理多个服务或多个协议。
目前支持I/O多路复用的系统调用有
select,pselect,poll,epoll
但select,pselect,poll,epoll本质上都是同步I/O。其中epoll时Linux系统独有的。也是要主要介绍的。

select

Python的select()方法直接调用操作系统的IO接口,它监控sockets,open files, and pipes(所有带fileno()方法的文件句柄)何时变成readable 和writeable, 或者通信错误,select()使得同时监控多个连接变的简单,并且这比写一个长循环来等待和监控多客户端连接要高效,因为select直接通过操作系统提供的C的网络接口进行操作,而不是通过Python的解释器。

select目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点。select的一 个缺点在于单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024,可以通过修改宏定义甚至重新编译内核的方式提升这一限制,但是这样会造成效率的降低

select(rlist, wlist, xlist, timeout=None)

select()方法接收并监控3个通信列表, 第一个rlist监控所有要进来的输入数据,第二个wlist是监控所有要发出去的输出数据,第三个监控异常错误数据,第四个设置指定等待时间,如果想立即返回,设为null即可,最后需要创建2个列表来包含输入和输出信息来传给select(),让select方法通过内核去监控,然后生成三个实例。zaipython中直接导入select使用。

epoll

epoll的方式,这种效率更高,但是这种方式在Windows下不支持,在Linux是支持的,selectors模块就是默认使用就是epoll,但是如果在windows系统上使用selectors模块,就会找不到epoll,从而使用select。

服务端代码:

import socketimport selectorsserver=socket.socket()server.bind(('0.0.0.0',8899))server.listen()epoll=selectors.DefaultSelector()def recv_func(conn):    data=conn.recv(1024)    if data==b'':        epoll.unregister(conn)        conn.close()    else:        print("接收到数据:>>>",data)        conn.send(data)def server_func(ser):    conn,addr=ser.accept()    print("连接处理!")    epoll.register(conn,selectors.EVENT_READ,recv_func)epoll.register(server,selectors.EVENT_READ,server_func)while True:    events=epoll.select()    for key,value in events:        callback=key.data        sock=key.fileobj        callback(sock)

客户端代码

import socketclient=socket.socket()client.connect(('127.0.0.1',8899))while True:    data=input("请输入传送的数据:>>>>")    client.send(data.encode())    print("接收到的数据:>>>",client.recv(1024).decode())

 

 

 

转载于:https://www.cnblogs.com/austinjoe/p/9661502.html

你可能感兴趣的文章
.NET笔试题(关于迭代的:遍历XML中的FileName)
查看>>
jQuery修改margin
查看>>
thread and process
查看>>
Corner case
查看>>
Anagrams
查看>>
ETL开发
查看>>
POJ 1166 The Clocks (爆搜 || 高斯消元)
查看>>
如何实现一个malloc
查看>>
javascript基础 之 void
查看>>
【DRP】【SQL】-悲观锁-防止多用户同时操作时出现脏数据
查看>>
MRC
查看>>
python_day25__02__异常处理__try---exception—else---finally
查看>>
常见的HTTP错误码
查看>>
python_集合(set)
查看>>
JS --正则表达式
查看>>
归并排序(分治)
查看>>
JavaScript中的流程控制
查看>>
js处理时间戳
查看>>
MySQL进阶11--DDL数据库定义语言--库创建/修改/删除--表的创建/修改/删除/复制
查看>>
[nRF51822] 13、浅谈nRF51822和NRF24LE1/NRF24LU1/NRF24L01经典2.4G模块无线通信配置与流程...
查看>>