python 实验普通IO和多路复用IO

普通IO方式

服务端:

# -*- coding: utf-8 -*-
"""
@Time    : 2021/6/19 10:12
@Author  : xiaochao
"""
import socket

# 创建一个socket
# socket.AF_INET 类型指明为网络连接;
# socket.SOCK_STREAM 表示当前连接为TCP连接
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定服务端,监听的端口
server_socket.bind(("localhost", 6999))
# 表示服务端,最多可接受5个等待的客户端连接;再多的连接请求会被拒绝
server_socket.listen(5)
print("Start server")
while True:
    # 等待某个客户端的连接,如果有多个客户端连接,后到的会排队
    conn, addr = server_socket.accept()
    print("Success connect with:%s." % str(addr))
    print(conn, addr)
    # 处理对当前客户端的连接请求
    # 当前和客户端建立连接后,会一直在此处理或等待;直到对方关闭连接
    while True:
        try:
            data = conn.recv(1024)
            print("receive:", data.decode())
            msg = "hi client:%s, I am server, and I get you message." % str(addr)
            conn.send(msg.encode("utf8"))
        except (ConnectionResetError, ConnectionAbortedError) as e:
            print("当前连接已关闭,client:%s." % str(addr))
            print(str(e))
            break
    conn.close()

客户端:

# -*- coding: utf-8 -*-
"""
@Time    : 2021/6/19 10:12
@Author  : xiaochao
"""
import socket
import time

# 创建客户端socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 与服务端建立连接
client_socket.connect(("localhost", 7999))
print("Success connect with server")
# 模拟发送10次消息
for i in range(10):
    time.sleep(5)
    msg = "hi server, I am client 1, message:%s." % i
    client_socket.send(msg.encode("utf8"))
    data = client_socket.recv(1024)
    print("Get server response:%s." % data.decode())
client_socket.close()

服务端多路复用:

# -*- coding: utf-8 -*-
"""
@Time    : 2021/6/19 10:12
@Author  : xiaochao
"""
import select
import socket

# 创建一个socket
# socket.AF_INET 类型指明为网络连接;
# socket.SOCK_STREAM 表示当前连接为TCP连接
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定服务端,监听的端口
server_socket.bind(("localhost", 7999))
# 设置非阻塞方式
server_socket.setblocking(False)
server_socket.listen(5)
print("Start server")

inputs = [server_socket, ]
while True:
    r_list, w_list, e_list = select.select(inputs, [], [], 3)
    for event in r_list:
        if event == server_socket:
            new_sock, addr = event.accept()
            print("Get new client:%s." % str(addr))
            inputs.append(new_sock)
        else:
            client_name = event.getpeername()
            data = event.recv(1024)
            if data:
                print("Receive client:%s msg:%s." % (client_name, data.decode()))
                msg = "hi client:%s, i am server." % str(client_name)
                event.send(msg.encode("utf8"))
            else:
                print("Connect close with client:%s." % str(client_name))
                inputs.remove(event)

创建两个客户端,连接多路复用的服务端,输出如下:

 

Start server
Get new client:('127.0.0.1', 51550).
Receive client:('127.0.0.1', 51550) msg:hi server, I am client 1, message:0..
Receive client:('127.0.0.1', 51550) msg:hi server, I am client 1, message:1..
Receive client:('127.0.0.1', 51550) msg:hi server, I am client 1, message:2..
Receive client:('127.0.0.1', 51550) msg:hi server, I am client 1, message:3..
Get new client:('127.0.0.1', 51555).
Receive client:('127.0.0.1', 51550) msg:hi server, I am client 1, message:4..
Receive client:('127.0.0.1', 51555) msg:hi server, I am client 2, message:0..
Receive client:('127.0.0.1', 51550) msg:hi server, I am client 1, message:5..
Receive client:('127.0.0.1', 51555) msg:hi server, I am client 2, message:1..
Receive client:('127.0.0.1', 51550) msg:hi server, I am client 1, message:6..
Receive client:('127.0.0.1', 51555) msg:hi server, I am client 2, message:2..
Receive client:('127.0.0.1', 51550) msg:hi server, I am client 1, message:7..
Receive client:('127.0.0.1', 51555) msg:hi server, I am client 2, message:3..
Receive client:('127.0.0.1', 51550) msg:hi server, I am client 1, message:8..
Receive client:('127.0.0.1', 51555) msg:hi server, I am client 2, message:4..
Receive client:('127.0.0.1', 51550) msg:hi server, I am client 1, message:9..
Connect close with client:('127.0.0.1', 51550).
Receive client:('127.0.0.1', 51555) msg:hi server, I am client 2, message:5..
Receive client:('127.0.0.1', 51555) msg:hi server, I am client 2, message:6..
Receive client:('127.0.0.1', 51555) msg:hi server, I am client 2, message:7..
Receive client:('127.0.0.1', 51555) msg:hi server, I am client 2, message:8..
Receive client:('127.0.0.1', 51555) msg:hi server, I am client 2, message:9..
Connect close with client:('127.0.0.1', 51555).

多路复用所带来的效果和好处,体现在以下两个方面:

1. 用一个线程,可以监控和处理多个文件描述符;

2. 将多个文件描述符的多次系统调用,优化为一次系统调用+内核层遍历文件描述符;

多路复用的文章参考:

你管这破玩意叫 IO 多路复用?_程序员小灰的博客-CSDN博客

Python实现socket的非阻塞式编程 - 简书 (jianshu.com)

原文地址:https://www.cnblogs.com/dasheng-maritime/p/14902845.html