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

Python中accept()方法与select()方法的结合应用

发布时间:2023-12-23 02:52:47

在Python中,accept()方法用于接受客户端的连接请求,select()方法用于多路复用地监测socket是否有数据可读。

下面是一个使用accept()方法和select()方法结合的示例,实现一个简单的多人聊天室:

import select
import socket
import sys

# 创建一个服务器socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind(('localhost', 1234))
server_socket.listen(10)

# 使用select方法进行IO多路复用
inputs = [server_socket]
outputs = []
message_queues = {}

while True:
    # 使用select方法监测socket是否有数据可读
    readable, writable, exceptional = select.select(inputs, outputs, inputs)

    for s in readable:
        if s is server_socket:
            # 有新的连接请求
            client_socket, client_address = s.accept()
            inputs.append(client_socket)
            message_queues[client_socket] = []
            print("新连接: %s" % client_address)
        else:
            # 有数据可读
            data = s.recv(1024)
            if data:
                # 将数据保存到该连接的消息队列
                message_queues[s].append(data)
                if s not in outputs:
                    outputs.append(s)
            else:
                # 客户端关闭连接
                if s in outputs:
                    outputs.remove(s)
                inputs.remove(s)
                s.close()
                del message_queues[s]

    for s in writable:
        # 有数据可写
        if len(message_queues[s]) == 0:
            outputs.remove(s)
        else:
            data = message_queues[s].pop(0)
            s.send(data)

    for s in exceptional:
        # 异常情况
        inputs.remove(s)
        if s in outputs:
            outputs.remove(s)
        s.close()
        del message_queues[s]

该示例中,首先创建一个服务器socket,并使用select方法对其进行监听。然后创建了三个列表inputs、outputs和message_queues,分别用于存储可读的socket、可写的socket和每个socket对应的消息队列。

进入主循环后,使用select方法进行IO多路复用,获取可读、可写和异常的socket列表。然后遍历可读的socket列表,如果是服务器socket,则表示有新的连接请求,接受连接,并将新连接的socket加入到inputs列表和message_queues字典中。如果是已经连接的客户端socket,则表示有数据可读,将数据保存到对应的消息队列中。

然后遍历可写的socket列表,如果消息队列不为空,则将队列中的数据发送出去。

最后遍历异常的socket列表,将异常的socket从inputs和outputs列表中移除,并关闭socket连接。

通过以上的例子,我们可以看到accept()方法和select()方法的结合能够实现一个基本的多人聊天室功能,同时解决了多个连接读写的问题。