python中io多路复用与非阻塞的应用

· Special

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

1

文本多客户端发送

服务端

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




python


评论

行为验证™ 安全组件加载中...
  1. 测试评论者

    开始测试