非阻塞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()



相关文章
相关标签/搜索