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

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 7
import socket,select

server = 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 7
import socket

client = 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()

你可能感兴趣的:(Python案例,python开发之路,I-O多路复用,python,网络编程,socket)