如何解析Python socket.recvfrom()返回的原始数据包并提取各字段值?
解决方案
你拿到的raw_data是完整的二进制网络数据包,包含IP头、TCP头等控制字段,本身不是纯文本,直接用UTF-8解码必然报错。以下是两种可行的字段提取方案:
方案1:使用Python标准库struct手动解析
无需安装第三方依赖,适合需要轻量实现的场景,按照网络协议的固定结构逐段解析即可:
import struct import socket # 解析基础IP头(前20字节为IPv4固定头长度) ip_header = raw_data[:20] # !代表网络字节序(大端),后面的字符对应各字段的类型 ip_fields = struct.unpack('!BBHHHBBH4s4s', ip_header) # 提取IP层字段 version_ihl = ip_fields[0] ip_version = version_ihl >> 4 ip_header_length = (version_ihl & 0x0F) * 4 ttl = ip_fields[5] protocol = ip_fields[6] # 6对应TCP协议,1对应ICMP,17对应UDP src_ip = socket.inet_ntoa(ip_fields[8]) dst_ip = socket.inet_ntoa(ip_fields[9]) print(f"IP版本: {ip_version}, 源IP: {src_ip}, 目的IP: {dst_ip}, 协议号: {protocol}") # 若为TCP协议,继续解析TCP头 if protocol == 6: tcp_header = raw_data[ip_header_length: ip_header_length + 20] tcp_fields = struct.unpack('!HHLLBBHHH', tcp_header) src_port = tcp_fields[0] dst_port = tcp_fields[1] seq_num = tcp_fields[2] ack_num = tcp_fields[3] tcp_header_length = (tcp_fields[4] >> 4) * 4 # 提取应用层payload(HTTP内容就在这里) payload = raw_data[ip_header_length + tcp_header_length:] # 仅payload部分需要解码,非文本内容可以指定errors参数避免报错 try: http_content = payload.decode('utf-8') except UnicodeDecodeError: http_content = payload.decode('latin-1', errors='replace') print(f"源端口: {src_port}, 目的端口: {dst_port}, HTTP内容: {http_content}")
方案2:使用scapy自动解析
无需手动计算协议字段偏移,适合快速开发的场景,操作步骤如下:
- 首先安装scapy:
pip install scapy - 直接调用接口解析原始数据包:
from scapy.layers.inet import IP, TCP # 直接传入原始字节即可完成全链路解析 packet = IP(raw_data) # 直接读取IP层字段 print(f"源IP: {packet.src}, 目的IP: {packet.dst}, TTL: {packet.ttl}") # 读取TCP层字段 if TCP in packet: tcp_layer = packet[TCP] print(f"源端口: {tcp_layer.sport}, 目的端口: {tcp_layer.dport}, 序列号: {tcp_layer.seq}") # 读取HTTP内容 http_payload = bytes(tcp_layer.payload) print(f"HTTP内容: {http_payload.decode('utf-8', errors='replace')}")
内容的提问来源于stack exchange,提问作者Riccardo Barbieri
相关产品推荐
相关产品推荐

