经常需要对UDP网络包进行抓包分析,常用的抓包软件不少,Wireshark、EtherPeek等等,自己开发的话用winpcap也是不错的选择。有时需要将抓取的包进行重放,可能就需要自己开发,EtherPeek有很好的抓包功能,但是重放功能不太好(可能是我不会用),只能对单个包进行重放或者全部包不分时间间隔的重放,所以需要对已经保存的pkt文件进行读取重放。
这篇文章(EtherPeek软件监听UDP网络报文解码)中对文件结构、方法等都进行了比较详细的描述。但是对于其中的关键的时间戳的解析却没有说,而且我感觉他给出的抓包头的结构中的字段也不对,自己对pkt文件研究后进行了修改,获取了正确的时间戳。
下面是主要的代码截取:
typedef unsigned short uint16;
typedef unsigned long uint32;
typedef unsigned char uint8;
typedef unsigned __int64 uint64;
typedef __int64 int64;
#ifundef INPUT
#define INPUT
#endif
#ifundef OUTPUT
#define OUTPUT
#endif
//包头结构
typedef struct tagPktPacketHeader
{
uint16 wID0;
uint32 dwLength;
uint16 wID1;
uint32 dwTime_low;//时间低32位
uint16 wID2;
uint32 dwTime_high;//时间高32位
uint16 wID3;
uint32 dwData1;
uint8 ucUnknown[8];
uint32 dwLength2;
}PktPacketHeader_S;
//时间结构
typedef struct tagTimeVal
{
long tv_sec;//秒
long tv_usec;//微妙
}TimeVal;
//转换时间常量
static const uint64 usecTo197001010000 = 11644473600000000;
//转换函数
double get_timestamp(INPUT PktPacketHeader_S &pack_header, OUTPUT TimeVal &tstamp)
{
uint64 tttemp = ((uint64)(((uint64)pack_header.dwTime_high)<<32|pack_header.dwTime_low)/1000)-usecTo197001010000;
tstamp.tv_sec = tttemp/1000000;
tstamp.tv_usec = tttemp%1000000;
return double((int64)tttemp/1000000.0);
}