You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Python select读列表中的套接字传入自定义recvAll函数?

使用Python select结合recvAll处理异步套接字读取

嘿,我来帮你梳理下怎么把select返回的可读套接字传给你的recvAll函数,其实核心思路就是利用select筛选出当前有数据的套接字,再逐个丢给你的函数处理就行。下面是具体的实现步骤和代码示例:

核心逻辑拆解

  • 先把你要监听的两个套接字放到一个可读列表里
  • 调用select.select()获取当前真正有数据可读的套接字集合
  • 遍历这个集合,把每个套接字传入recvAll读取完整数据

完整代码示例(兼容Python3)

import select
import socket
from errno import errorcode

def recvAll(sock):
    buffer = b''  # 注意:Python3里recv返回bytes,用bytes存储更稳妥
    data_chunks = []
    try:
        while True:
            chunk = sock.recv(8192)
            if not chunk:
                # 对方关闭套接字,停止读取
                break
            data_chunks.append(chunk)
            # 如果你是基于应用层协议判断是否收完(比如有长度头),可以在这里加判断逻辑
            # 不过你的需求是读取全部数据直到套接字关闭,所以保持循环即可
    except OSError as e:
        # 替换Python2的error异常,10035是非阻塞套接字的正常"暂时无数据"错误
        if e.errno != 10035:
            print(f"套接字错误:{errorcode[e.errno]} - {e.strerror}")
            # 这里可以根据业务需求添加错误处理,比如断开连接等
    return b''.join(data_chunks)

# 初始化两个要监听的套接字(假设已经完成连接/监听)
sock_a = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock_a.connect(('target-host-1.com', 80))
sock_b = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock_b.connect(('target-host-2.com', 80))

# 维护要监听的可读套接字列表
read_list = [sock_a, sock_b]

while True:
    # 调用select,阻塞直到有套接字可读、可写或异常
    readable, _, exceptional = select.select(read_list, [], read_list)
    
    # 处理可读的套接字
    for sock in readable:
        full_data = recvAll(sock)
        if full_data:
            print(f"从 {sock.getpeername()} 收到完整数据:\n{full_data}")
        else:
            # 收到空数据说明套接字已关闭,从监听列表移除并关闭
            print(f"套接字 {sock.getpeername()} 已断开连接")
            read_list.remove(sock)
            sock.close()
    
    # 如果没有需要监听的套接字了,退出循环
    if not read_list:
        break

# 处理异常套接字(可选)
for sock in exceptional:
    print(f"套接字 {sock.getpeername()} 发生异常")
    read_list.remove(sock)
    sock.close()

几个关键注意点

  • 字节类型适配:Python3中sock.recv()返回的是bytes对象,不是字符串,所以recvAll里的缓冲区要改成bytes类型,避免编码报错
  • 异常处理更新:Python2的error异常在Python3中统一为OSError,需要调整捕获方式;而10035错误是非阻塞套接字的正常情况,表示当前没有更多数据可读,所以可以忽略这个异常
  • 套接字生命周期管理:当recvAll返回空时,说明对方已经关闭了套接字,一定要把它从监听列表里移除并关闭,不然select会一直触发这个套接字的可读事件
  • 协议适配:如果你的应用层协议有固定的报文格式(比如带长度前缀),可以在recvAll里加判断逻辑,不用等到套接字关闭就停止读取,这样效率更高

内容的提问来源于stack exchange,提问作者nb12345

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:53:46