#方法: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()
![]()