Python案例-网络编程-I/O多路复用-select方法用例

来源:互联网 发布:Ubuntu chrome设置中文 编辑:程序博客网 时间:2024/06/02 04:06

I/O多路复用(I/O multiplexing),可以简要理解为:多条socket复用一个I/O管理线程;

存在意义:用来监听和管理socket连接是否有变化。

早期管理方法:多进程并发模型(每一个socket,分配一个独立的进程来管理)
近期管理方法:I/O多路复用(单个线程通过跟踪记录每个socket的状态来管理多个socket连接)
详细解释可以点击此处


实现I/O多路复用主要有三种方法:select、poll、epoll(按照出现的先后顺序)
以下简要讲一下Python中的三种方法:

select:

内部的方法就是一个类似for循环的处理,其在不断的进行检查socket对象是否改变,但是受限于监听的1024连接上限
select有以下缺点:
1、有1024个连接的上限;
2、会修改传入的参数数组;
3、如果任何一个socket(I/O stream)出现了数据变化,select 仅仅会返回,但是并不会告诉管理端是那个sock上有变化,因此就得for循环去挨个查,socket数量少时还可以,要是几W条,那就太浪费资源了;

poll:

去掉了select的1024上限,不再修改参数数组,但本质依然是类似for循环的处理;

epoll:

内部监听机制改变了,以前的select、poll是server去循环的挨个检查监听的socket连接,而epoll则是socket状态一旦改变,就会主动给epoll-server通知一下;

熟悉zabbix收集消息的方式的同学,可以理解为zabbix就是socket管理程序select、poll就是其被动机制;epoll为主动机制;

用途:可以用来监听 I/O stream 即:既监听socket,也监听 数据读写,但是不支持文件处理类的监听


下面分享一下python中select的使用方法:

socket-server:

#!/usr/bin/env python# -- coding = 'utf-8' --# Author Allen Lee# Python Version 3.5.1# OS Windows 7import socket,selectserver = socket.socket()server.bind(('127.0.0.1',8808,))server.listen(5)inputs = [server,]outputs = []messages = {}xlist = []while True:    """    select的    第一个参数为监听有数据变化的socket对象,并放到rlist中;                第二个参数为只要写入wlist,不论是否变化,都会被监听;                第三个参数为,如果某个socket报错了就计入xlist;                最后一个参数为间隔时间    """    rlist,wlist,xlist = select.select(inputs,outputs,xlist,1)    print(len(inputs),len(rlist),len(outputs),len(wlist))    for i in rlist:        if i == server:            conn,addr = i.accept()            inputs.append(conn)            conn.sendall(bytes('hello',encoding='utf-8'))        else:            print('===============')            try:                res_data = conn.recv(1024)                if not res_data:                    raise Exception("断开连接")                else:                    outputs.append(i)                    messages[r].append(res_data)            except Exception as e:                inputs.remove(r)                del messages[i]    for w in wlist:        msg = messages[w].pop()        resp = msg + bytes('response',encoding='utf-8')        w.sendall(resp)        outputs.remove(w)

socket-client:

#!/usr/bin/env python# -- coding = 'utf-8' --# Author Allen Lee# Python Version 3.5.1# OS Windows 7import socketclient = socket.socket()client.connect(('127.0.0.1',8808,))print(str(client.recv(1024),encoding='utf-8'))while True:    send_file = input('>>:').strip()    if send_file == 'exit':break    send_data = bytes(send_file,encoding='utf-8')    client.sendall(send_data)    print(str(client.recv(1024),encoding='utf-8'))client.close()
0 0
原创粉丝点击