非阻塞IO模型解決阻塞IO(socket例子)

#方法:sk.setblocking(False)

#服務器端:
import socket
sk=socket.socket()
sk.setblocking(False)
sk.bind(('127.0.0.1',8080))
sk.listen()
#定義空列表用於存放各個conn
Conn_List = []
#定義刪除列表用於刪除Conn_List中斷開鏈接的客戶端conn
Conn_Del = []

while 1:
    try:
        conn,addr = sk.accept() #若是是阻塞IO,此時程序會一直在這裏等待
        Conn_List.append(conn)  #將監聽到的conn對象放到conn列表中,即爲多客戶端鏈接
    except BlockingIOError:
        '''若是try中沒有客戶端鏈接,則執行該代碼塊,判斷客戶端是否向服務器發送數據'''
        #遍歷conn列表,看看有沒有客戶端發送數據
        for conn in Conn_List:
            try:
                #嘗試接收數據
                info = conn.recv(1024).decode('utf-8')
                #注意!若是客戶端正常關閉,即客戶端執行了close,服務器會接收到一個空
                if not info:
                    #若是收到空,證實客戶端斷開鏈接,將該conn添加到刪除列表中,用於後面刪除Conn_List中對應的conn
                    Conn_Del.append(conn)
                    print('客戶端已經斷開鏈接了')
                    #在服務器中關閉對應的conn
                    conn.close()
                else:
                    '''服務器邏輯層'''
                    # 若是收到客戶端的數據,邏輯層返回數據給客戶端
                    print('這是接收到來自客戶端{}的數據:{}'.format(conn,info))
                    #返回數據給客戶端(例如將客戶端的數據小寫轉爲大寫返回給客戶端)
                    conn.send(info.upper().encode('utf-8'))
            except BlockingIOError:
                '''若是本次循環中該conn沒有發送數據,則執行該代碼塊,即對下一個conn通訊'''
                continue
            except ConnectionResetError:
                '''若是本次循環中該conn強制退出,則不執行任何操做'''
                pass
        #刪除列表刪除Conn_List中已經正常斷開鏈接的客戶端conn
        if Conn_Del:
            for conn in Conn_Del:
                Conn_List.remove(conn)
            #在刪除完正常關閉連接的客戶端後,應該把刪除列表清空,不然會報錯
            Conn_Del = []
            
            
#客戶端:
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()



相關文章
相關標籤/搜索