欢迎访问宙启技术站
智能推送

利用selectors模块实现Python中的TCP/IP通信

发布时间:2023-12-24 04:22:27

Python中的selectors模块是一个高级的I/O多路复用库,它可以有效地处理多个socket通信。在TCP/IP通信中,使用selectors模块可以实现同时处理多个客户端的连接请求和数据传输。下面是一个使用selectors模块实现TCP/IP通信的例子:

import selectors
import socket

# 创建一个selectors对象
sel = selectors.DefaultSelector()

# 定义服务器地址和端口
HOST = 'localhost'
PORT = 8080

# 创建服务器socket并绑定地址和端口
server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_sock.bind((HOST, PORT))
server_sock.listen()

print("服务器启动,监听地址为{},端口为{}".format(HOST, PORT))

# 设置为非阻塞模式
server_sock.setblocking(False)

# 注册服务器socket,监听事件为读事件
sel.register(server_sock, selectors.EVENT_READ, data=None)

# 处理连接请求和数据传输
def accept(sock):
    conn, addr = sock.accept()
    print("客户端{}已连接".format(addr))

    # 设置为非阻塞模式
    conn.setblocking(False)

    # 创建客户端socket
    data = types.SimpleNamespace(addr=addr, inb=b'', outb=b'')
    events = selectors.EVENT_READ | selectors.EVENT_WRITE
    sel.register(conn, events, data=data)

def recv(sock, data):
    recv_data = sock.recv(1024)
    if recv_data:
        data.outb += recv_data
    else:
        addr = data.addr
        print("客户端{}已断开连接".format(addr))
        sel.unregister(sock)
        sock.close()

def send(sock, data):
    if data.outb:
        send_data = data.outb
        data.outb = b''
        sock.sendall(send_data)

# 循环监听事件
while True:
    # 获取所有已就绪的事件列表
    events = sel.select()

    # 处理每一个已就绪的事件
    for key, mask in events:
        sock = key.fileobj
        data = key.data

        # 如果是服务器socket,则调用accept函数处理连接请求
        if sock == server_sock:
            accept(sock)
        # 如果是客户端socket且有读事件,则调用recv函数接收数据
        elif mask & selectors.EVENT_READ:
            recv(sock, data)
        # 如果是客户端socket且有写事件,则调用send函数发送数据
        elif mask & selectors.EVENT_WRITE:
            send(sock, data)

在这个例子中,我们使用默认的selectors对象 selectors.DefaultSelector() ,创建服务器socket并绑定地址和端口,然后将服务器socket注册到selectors对象中,监听读事件。当有客户端连接请求时,调用accept函数处理连接请求,并创建客户端socket并注册到selectors对象中,监听读和写事件。当客户端有数据到达时,调用recv函数接收数据,并将准备发送的数据添加到outb中。当客户端socket可写时,调用send函数发送数据。

通过上面的例子,我们可以实现一个简单的TCP/IP通信程序,并同时处理多个客户端的连接请求和数据传输。selectors模块提供了很多功能丰富的API,可用于更高级的I/O多路复用操作。