应用类型包括,文本多客户端下载与服务器文件多线程下载。

文本多客户端发送
服务端
import socket
import select
#非阻塞和io多路复用
#设置服务端对象
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setblocking(False)
server.bind(('127.0.0.1', 9999))
server.listen(5)
#设置监听对象
listen_device = [server,]
while True:
#设置io多路复用对象
#循环监听对象
r,w,e = select.select(listen_device,[],[],0.05)
#判断监听对象,并分流执行路径
for sock in r:
if sock == server:
conn,addr = server.accept()
print('已链接')
listen_device.append(conn)
else:
data = sock.recv(1024)
if data:
print(f'收到内容: ',data.decode())
else:
print('关闭链接')
listen_device.remove(sock)
客户端
import socket
import select
#io多路复用客户端
#创建对象
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#发送内容
while True:
client.connect(('127.0.0.1', 9999))
while True:
user_input = input('>>> ').strip()
if user_input.upper() == 'Q':
break
client.sendall(user_input.encode())
client.close()
客户端文件多线程下载
import socket
import select
import uuid
import os
#创建客户端对象
#对象字节缓冲区
data_buffer = {}
recv_list = []
for i in range(5):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#设置对象非阻塞
sock.setblocking(False)
try:
sock.connect(('127.0.0.1', 5244))
except BlockingIOError:
pass
recv_list.append(sock)
data_buffer[sock] = b''
#循环监听对象,处理请求并下载
has_send_list = []
while True:
r,w,e = select.select(has_send_list,recv_list , [],0.1)
#循环发送请求
for sock in w:
# sock.sendall(b"GET /d/local/1.png HTTP/1.1\r\nHost:127.0.0.1\r\n\r\n")
request = (
b"GET /d/local/1.png HTTP/1.1\r\n"
b"Host: 127.0.0.1\r\n"
b"Connection: close\r\n\r\n"
)
sock.sendall(request)
#对象删除等待名单
recv_list.remove(sock)
#对象增加处理名单
has_send_list.append(sock)
for sock in r:
try:
data = sock.recv(8192)
#判断是否下载完毕
if data:
data_buffer[sock] += data
else:
print(f'下载完毕{sock.fileno()}')
full_data = data_buffer[sock]
content = full_data.split(b'\r\n\r\n')[-1]
#储存对象
#对象名称
file_name = f'{str(uuid.uuid4())}.png'
file_path = os.path.join('images', file_name)
with open(file_path, 'wb') as f:
f.write(content)
has_send_list.remove(sock)
except Exception as e:
print('错误为: ',e)
if not has_send_list and not recv_list:
break
开始测试