基于select的网络IO模型

本秂侑毒 提交于 2019-12-01 22:28:44
#select  和    poll    和epoll的区别
    '''
      select和poll有一个共同的机制,都是采用轮训的方式去询问内核,有没有数据准备好了
      select有一个最大监听事件的限制,32位机限制1024,,6位机限制2048
      poll没有,理论上poll可以开启无限大,1G内存大概够你开10W个事件去监听
      epoll是最好的,采用的是回调机制,解决了select和poll共同存在的问题
      而且epoll理论上也可以开启无限多个监听事件
    '''

# IO多路复用
    '''
        阻塞IO
        非阻塞IO
        多路复用IO
        异步IO python实现不了,但是有tornado框架,天生自带异步
    '''

#服务器端
import socket
import select

sk=socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen()

Conn_Del = []        #定义删除列表
rlist = [sk]         #是用来让select帮忙监听的所有接口
# select:windows/linux是监听事件有没有数据到来
# poll:  linux   也可以做select的工作
# epoll: linux   也可以做类似的工作

while 1:
    r,w,x = select.select(rlist,[],[])  #将rlist传给select,当rlist中哪个接口有反应,就返回给r这个列表
    if r:
        for i in r:                     #循环遍历,看看有反应的接口是sk还是conn,因为如果是sk,后面会把conn也加到这个列表中
            if i == sk:
                #如果是sk,表明有客户端的连接请求
                conn,addr = i.accept()
                rlist.append(conn)      #把新的客户端的连接,添加到rlist,继续让select帮忙监听
            else:
                #如果是conn,代表客户端请求发送数据了(此时客户端已经连接上了)
                #下面的异常处理模型和非阻塞IO模型解决阻塞IO模型类似
                try:
                    msg = i.recv(1024).decode('utf-8')
                    if not msg:
                        #客户端正常关闭返回给服务器端一个空,即客户端执行了close()
                        Conn_Del.append(i)
                        i.close()
                    else:
                        #服务器端的逻辑层(以字符串大写的形式返回给客户端)
                        print("接收到来自{}客户端的消息{}".format(i,msg))
                        i.send(msg.upper().encode('utf-8'))
                except ConnectionResetError:
                    #客户端强制关闭
                    pass

        if Conn_Del:
            for conn in Conn_Del:
                rlist.remove(conn)
            Conn_Del.clear()


sk.close()




#客户端
import socket
sk = socket.socket()
sk.connect(('127.0.0.1',8080))

while 1:
    msg_s = input('>>>')
    if not msg_s:continue
    if msg_s == 'q':break
    sk.send(msg_s.encode('utf-8'))
    print(sk.recv(1024).decode('utf-8'))
sk.close()

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!