理解select模块--等待IO完成


用一句话描述select是做什么的: 等待IO完成.
怎么理解
在没有select模块时,通常的socket通信如下
服务器server.py

#encoding=utf-8
import socket


def main():
    '''阻塞'''
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('0.0.0.0', 8080))
    sock.listen(5)
    while True:
        client_sock, address = sock.accept()
        client_sock.settimeout(5)
        msg = client_sock.recv(1024)
        if msg == '1':
            client_sock.send('welcome to server!')
        else:
            client_sock.send('please go out!')
        client_sock.close()


if __name__ == '__main__':
    main()

客户端client.py

#encoding=utf-8
import socket
import time


def main():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect(('0.0.0.0', 8080))
    time.sleep(2)
    sock.send('1')
    print sock.recv(1024)
    sock.close()


if __name__ == '__main__':
    main()

启动server.py之后,它会停在socket.accept()上,除了等待,程序再也不能做其它事情了。这样的IO等待,极大影响程序效率。

很自然的会想: 有什么办法把这个等待过程独立出来,不让它影响到整个程序?
select模块就是为了解决这个问题的.

替换上面的server.py

#encoding=utf-8
import socket


def main():
    '''非阻塞'''
    import select

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(("0.0.0.0", 8080))
    sock.listen(5)
    while True:
        # 传入需要等待的socket,返回准备好的socket
        infds, outfds, errfds = select.select([sock, ], [], [], 5)
        print infds, outfds, errfds
        # 返回准备好的fd
        if sock in infds:
            client_sock, clientaddr = sock.accept()
            msg = client_sock.recv(8196)
            if len(msg) != 0:
                print (msg)
            client_sock.close()
        print "no data coming"


if __name__ == '__main__':
    main()

上面用法就是将需要等待IO的socket作为参数传入,返回准备好的socket.
即select负责IO等待,当IO准备好了,就将它回返.
这就是select做的事情.

select()说明
select.select(rlist, wlist, xlist[, timeout])
rlist 等待直到准备好读--为输入而观察的文件对象列表
wlist 等待直到准备好写--为输出而观察的文件对象列表
xlist 等待一种意外的情况--观察错误异常的文件列表
timeout 单位是seconds,
默认是timeout=None表示select永远阻塞,直到一个fd准备好
timeout=0 表示不会阻塞
timeout=10 表示最多阻塞10秒,在阻塞期间发现有准备好的文件对象,会立刻退出阻塞状态.
return:返回参数rlist, wlist, xlist中准备好的文件对象,没有则返回([], [], [])



上篇: socket.error: [Errno 32] Broken pipe错误的原因 下篇: jquery对象是否相同