用select實現socket的IO多路複用

這個寫的是服務端,客戶端比較簡單,就不寫啦!

import socket
import select
import queue
server=socket.socket()
server.bind(('localhost',9000))
# 對於IO多路複用須要設置爲非阻塞模式
server.setblocking(False)
server.listen(1024)
msg_dic={}
inputs=[server]
outputs=[]
# select須要循環監聽,因此這裏添加死循環
while True:
    in_list,out_list,except_list=select.select(inputs,outputs,inputs)
    for i in in_list:
        if i is server:#有新連接進來
            conn,addr=i.accept()
            inputs.append(conn)
            # 給每個連接賦值成一個隊列
            msg_dic[conn]=queue.Queue()
            # 其實select監測到的返回值不該該是具體的某一個conn,可是python的select作了封裝,因此能夠直接使用
        else:#有消息須要接收
            data=i.recv(1024)
            print(data)
            #如下代碼是爲了把要返回的數據放入某一個連接的隊列裏
            msg_dic[i].put(data)
            #放完數據還要把該連接放入outputs隊列,以便在下次select循環監聽時,發送數據
            outputs.append(i)
    # 這裏在每次監聽的最後返回上次conn須要返回的數據,其實能夠直接返回數據的,這裏這樣寫是爲了裝個逼
    for j in out_list:
        j.send(msg_dic[j].get())
        # 發送完數據就從須要返回消息的隊列裏清除該連接
        outputs.remove(j)

    for e in except_list:
        # 連接出現異常,就再也不返回數據,select也再也不循環監聽,消息隊列也須要抹去這條數據
        if e in outputs:
            outputs.remove(e)
        inputs.remove(e)
        del msg_dic[e]
相關文章
相關標籤/搜索