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

为何无法同时使用dpkt.http.Response与dpkt.http.Request?

问题原因分析

你的代码无法输出res : ~~的核心原因有两个:

  1. TCP分片导致HTTP响应不完整:HTTP响应被拆分为两个TCP包传输,第一个包仅包含响应头,第二个包仅包含响应体。dpkt.http.Response只能解析符合HTTP规范的完整响应单元(状态行+头部+完整body,或至少是能被识别为完整响应的结构),单独的响应体无法被解析为合法的Response对象;而第一个响应包虽然有完整的响应头,但Content-Length字段声明了body长度为615,当前包却没有body内容,dpkt解析时会抛出异常,被你代码里的except: pass直接吞掉,因此没有输出。
  2. 无差别异常捕获掩盖错误:except: pass会捕获所有异常,包括解析失败的错误,导致你无法排查问题所在。
正确实现方法

要解决这个问题,必须重组TCP流——因为HTTP是基于TCP的流式协议,单包无法保证是完整的HTTP请求/响应。以下是修正后的代码:

import pcap
import dpkt
from collections import defaultdict

# 维护TCP流:键是(src_ip, src_port, dst_ip, dst_port),值是待拼接的数据流
tcp_streams = defaultdict(bytes)
nonErrorCode = ['200']

sniffer = pcap.pcap(name='cali7f35c4176d5@if3', promisc=True, immediate=True, timeout_ms=50)
sniffer.setfilter('tcp and port 80')

for t, p in sniffer:
    try:
        eth = dpkt.ethernet.Ethernet(p)
        ip = eth.data
        tcp = ip.data

        # 跳过无数据的TCP包
        if len(tcp.data) == 0:
            continue

        # 生成TCP流的唯一标识(双向,方便匹配请求和响应)
        stream_key_req = (ip.src, tcp.sport, ip.dst, tcp.dport)
        stream_key_res = (ip.dst, tcp.dport, ip.src, tcp.sport)

        if tcp.dport == 80:
            # 请求流:拼接数据,尝试解析HTTP请求
            tcp_streams[stream_key_req] += tcp.data
            try:
                req = dpkt.http.Request(tcp_streams[stream_key_req])
                print(f'req : {repr(req)}')
                # 解析成功,清空该流的缓存(避免重复解析)
                tcp_streams[stream_key_req] = b''
            except dpkt.NeedData:
                # 数据不完整,继续等待后续包
                pass
        elif tcp.sport == 80:
            # 响应流:拼接数据,尝试解析HTTP响应
            tcp_streams[stream_key_res] += tcp.data
            try:
                res = dpkt.http.Response(tcp_streams[stream_key_res])
                print(f'res : {repr(res)}')
                # 检查响应状态码
                if res.status not in nonErrorCode:
                    print(f'*错误响应*: {res.status} {res.reason}')
                # 解析成功,清空该流的缓存
                tcp_streams[stream_key_res] = b''
            except dpkt.NeedData:
                # 数据不完整,继续等待后续包
                pass
    except Exception as e:
        # 捕获并打印异常,方便调试,避免无脑吞掉错误
        print(f'处理数据包时出错: {e}')
关键改进点
  • TCP流重组:用defaultdict维护每个TCP连接的数据流,将同一连接的数据包按顺序拼接,直到能解析出完整的HTTP请求/响应。
  • 针对性异常处理:只捕获dpkt.NeedData异常(表示数据不完整,需要继续等待),其他异常打印出来方便调试。
  • 解析成功后清空缓存:避免重复解析同一请求/响应的数据流。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 16:05:37