网络I/O模型

    一、阻塞型

    阻塞型I/O模型一次只能处理一个连接,每次遇到都会阻塞,等待操作系统将数据返回,处理效率不高。阻塞型I/O模型示例:

    

#普通的socket服务端程序都是I/O阻塞的
import socket
phone=socket.socket()
phone.bind(('127.0.0.1',8081))
phone.listen()

while True:
    conn,addr=phone.accept()

    while True:
        try:
            data=conn.recv(1024)
            conn.send(data.upper())
        except Exception:
            break
    conn.close()
phone.close()

 

  二、非阻塞型I/O模型

  非阻塞型I/O模型再遇到I/O阻塞时不会一直等待操作系统将数据返回,而是在操作系统准备的过程中执行其他任务,之后在去跟操作系统确认数据是否准备完毕,不建议使用占用CPU太高。非阻塞I/O模型代码示例:

  

from socket import *
s=socket()
s.bind(('127.0.0.1',8080))
s.listen()
s.setblocking(False) #设置I/O不阻塞,没有数据返回就抛出BlockingIOError异常

conn_l=[]
del_l=[]
while True:
    try:
        conn,addr=s.accept()
        conn_l.append(conn)
    except BlockingIOError: #捕捉到BlockingIOError异常就执行其他任务
        for conn in conn_l:
            try:
                data=conn.recv(1024)
                conn.send(data.upper())
            except BlockingIOError:
                pass
            except ConnectionResetError:
                del_l.append(conn)
        for conn in del_l:
            conn.close()
            conn_l.remove(conn)
        del_l.clear()

 

  三、I/O多路复用

  I/O多路复用就是同时监听多个连接的I/O状态,然后把就绪的连接返回出来做数据处理,它相比于阻塞型I/O模型的优势在于能够同时处理多个连接,不适合处理单个连接。同时epoll模型在I/O监听的处理效率上比select效率高,因为它是采用连接主动通知的方式告诉监听程序哪个连接已经就绪,而select则是一个个去检测,但是epoll只支持Linux。I/O多路复用的示例:

  

from socket import *
import select
s=socket()
s.bind(('127.0.0.1',8080))
s.listen()
s.setblocking(False)

s_l=[s,]
while True:
    r_l,_,_=select.select(s_l,[],[])   #select模块第一个列表是可以开始接收数据的socket对象集合,第二个列表是可以开始发送数据的socket对象集合,第三个列表是连接出错的socket对象;select模块可以监测任何有fileno方法的对象
    for obj in r_l:
        if obj==s:
            conn,addr=obj.accept()
            s_l.append(conn)
        else:
            data=obj.recv(1024)
            obj.send(data.upper())

 

posted @ 2017-09-12 20:10  魅力宁波  阅读(198)  评论(0)    收藏  举报