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

Python中正确处理TCP流并按行拆分:解决半行数据问题

解决TCP连接下HTTP行拆分不完整的问题

你的核心问题是没有严格按照HTTP的\r\n行分隔规则处理缓冲区数据,原代码依赖BytesIO的默认行迭代(按\n分割),且未正确保留不完整的行,导致慢连接下半行数据被错误传入handle_line。以下是具体解决思路:

思路1:用字节缓冲区手动拆分完整行

放弃BytesIO,改用一个字节变量存储未处理的剩余数据,每次接收新数据后按\r\n拆分,只处理完整的行,不完整的留到下一轮:

def listener(client, address):
    try:
        remaining_data = b''  # 存储未处理的半行数据
        while True:
            resp = client.recv(1024)
            if not resp:
                logging.info('Connection closed by ' + str(address))
                break
            remaining_data += resp
            # 按\r\n拆分,最后一个元素是不完整的行(或空字符串)
            lines = remaining_data.split(b'\r\n')
            # 留存不完整的行到下一次处理
            remaining_data = lines[-1]
            # 遍历处理所有完整行
            for line in lines[:-1]:
                if line:  # 跳过HTTP头结束时的空行
                    handle_line(client, line + b'\r\n')  # 还原行尾分隔符,可根据handle_line需求调整
    except IOError as e:
        if e.errno == errno.EPIPE:
            logging.warning(e)
        else:
            logging.warning(e)
    finally:
        client.close()

思路2:用BytesIO配合指定分隔符的readline

如果坚持用BytesIO,可以用readline指定\r\n作为分隔符,仅读取完整的行:

def listener(client, address):
    try:
        with BytesIO() as buffer:
            while True:
                resp = client.recv(1024)
                if not resp:
                    logging.info('Connection closed by ' + str(address))
                    break
                buffer.write(resp)
                buffer.seek(0)
                # 循环读取所有完整的\r\n结尾行
                while True:
                    line = buffer.readline(b'\r\n')
                    if not line:  # 没有完整行,退出循环
                        break
                    handle_line(client, line)  # readline会保留末尾的\r\n
                # 留存剩余的半行数据
                remaining = buffer.read()
                buffer.truncate(0)
                buffer.write(remaining)
    except IOError as e:
        if e.errno == errno.EPIPE:
            logging.warning(e)
        else:
            logging.warning(e)
    finally:
        client.close()

关键注意点

  • 必须严格以\r\n作为行分隔符,不能依赖默认的\n分割,否则会误判不完整的行
  • 无论哪种方案,都要确保只有包含完整\r\n的行才会传给handle_line,不完整的部分必须留到下一次接收新数据后再处理
  • 原代码中的time.sleep(0.5)完全无效,慢连接下数据是分批到达的,休眠无法保证收到完整行,必须通过缓冲区拼接+分隔符判断来处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 04:57:23