You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何修改Python原始套接字服务端代码提取UDP数据包中的消息?

提取UDP数据包中的消息内容

我来帮你搞定这个问题——现在你的服务端打印的是整个数据包(包含IP头、UDP头和实际消息内容),我们只需要定位到UDP负载的起始位置,提取并解码这部分内容就能只打印"Hello"了。

修改思路

  • UDP头固定为8字节,加上IP头的长度(iph_length),就能得到实际消息的起始索引:iph_length + 8
  • 从这个索引开始截取数据包的剩余部分,就是客户端发送的字节数据
  • 将字节数据解码为字符串(客户端用encode()默认采用UTF-8编码,解码时对应使用utf-8即可)
  • 另外要修正原代码中缺失的sys模块导入,否则sys.exit()会触发报错

修改后的完整服务端代码

import socket
import sys  # 补充导入sys模块,修复exit报错
from struct import *

def PacketMonitoring():
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_UDP)
    except socket.error as e:
        print("Errornya: ", e)
        sys.exit()
    
    while True:
        packet = sock.recvfrom(65535)[0]
        
        # 解析IP头
        ip_header = packet[0:20]
        iphead = unpack("!BBHHHBBH4s4s", ip_header)
        version_ihl = iphead[0]
        ihl = version_ihl & 0xF
        iph_length = ihl * 4
        
        # 定位UDP负载起始位置,提取并解码消息
        udp_payload_start = iph_length + 8  # IP头长度 + UDP头长度(固定8字节)
        message = packet[udp_payload_start:].decode('utf-8')
        
        # 获取源IP和目标端口
        source_addr = socket.inet_ntoa(iphead[8])
        dest_port = unpack("!HHHH", packet[iph_length:iph_length+8])[1]
        
        print("\nSource IP address: ", source_addr)
        print("Destination Port: ", dest_port)
        print("Message: ", message)  # 仅打印解码后的实际消息

if __name__ == "__main__":
    PacketMonitoring()

关键修改点说明

  1. 补充sys模块导入:原代码使用了sys.exit()但未导入sys,会导致运行时抛出NameError
  2. 计算负载起始位置:通过iph_length + 8跳过IP头和UDP头,直接定位到实际消息内容
  3. 解码字节数据:将截取到的字节数据用decode('utf-8')转换为可读字符串
  4. 优化端口获取:可以直接在解包UDP头时获取目标端口,避免重复操作(原写法也可正常运行,这里是小优化)

这样修改后,服务端就会精准打印客户端发送的"Hello"消息了。

内容的提问来源于stack exchange,提问作者M. Arie

火山引擎 最新活动