那位大侠帮我看看这个sniffer,为什么TCP和UDP的端口号和数据包长度都不正确啊,
源ip和目标ip都是正确的。#include <winsock2.h>
#include <ws2tcpip.h>
#include <iostream>
using namespace std;
#define BUFFER_SIZE 1500
#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)
typedef struct _TCP  //应用层,传输层层
{
unsigned short SrcPort; // 源端口
unsigned short DstPort; // 目的端口
DWORD SeqNum; // 顺序号
DWORD AckNum; // 确认号
BYTE DataOff; // TCP头长
BYTE Flags; // 标志(URG、ACK等)
WORD Window; // 窗口大小
WORD Chksum; // 校验和
WORD UrgPtr; // 紧急指针
} TCP;
typedef TCP *LPTCP;
typedef TCP UNALIGNED * ULPTCP;typedef struct _IP  //传输层,网络层
{
union   { 
BYTE   Version;   //   版本 
BYTE   HdrLen;   //   IHL 
                }; 
BYTE ServiceType; // 服务类型
unsigned short TotalLen; // 总长
WORD ID; // 标识
union{   
WORD   Flags;   //   标志 
WORD   FragOff;   //   分段偏移 
}; 
BYTE TimeToLive; // 生命期
BYTE Protocol; // 协议
WORD HdrChksum; // 头校验和
DWORD SrcAddr; // 源地址
DWORD DstAddr; // 目的地址
BYTE Options; // 选项
} IP;
typedef struct _UDPHDR{
    unsigned short   nPortSrc;           
    unsigned short   nPortDst;        
    unsigned short   nLen;           
    unsigned short   nChk;       
}UDP;typedef IP * LPIP;
typedef IP UNALIGNED * ULPIP;
#define PROTOCOL_STRING_ICMP_TXT "ICMP"
#define PROTOCOL_STRING_TCP_TXT "TCP"
#define PROTOCOL_STRING_UDP_TXT "UDP"
#define PROTOCOL_STRING_SPX_TXT "SPX"
#define PROTOCOL_STRING_NCP_TXT "NCP"
#define PROTOCOL_STRING_UNKNOW_TXT "UNKNOW"
char* GetProtocolTxt(int Protocol)
{
switch (Protocol)
{
case IPPROTO_ICMP : //1
return PROTOCOL_STRING_ICMP_TXT;
case IPPROTO_TCP : //6
return PROTOCOL_STRING_TCP_TXT;
case IPPROTO_UDP : //17
return PROTOCOL_STRING_UDP_TXT;
default:
return PROTOCOL_STRING_UNKNOW_TXT;
}
}
void main()
{
WSADATA wsadata;
// 检查 Winsock 版本号,WSAData为WSADATA结构对象
int erro=WSAStartup(MAKEWORD(1, 1), &wsadata);
if(erro!=0)
{
cout<<"初始化失败"<<endl;
return ;
}
// 创建原始套接字
SOCKET sock;
sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP); BOOL flag=TRUE;
setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char*)&flag, sizeof(flag));    char LocalName[512];
gethostname((char*)LocalName, sizeof(LocalName)-1); hostent * pHost;
    pHost=gethostbyname((char*)LocalName);
  
SOCKADDR_IN addr_in;
addr_in.sin_addr= *(in_addr *)pHost->h_addr;//h_addr_list[0]; //IP h_addr定义的宏
addr_in.sin_family = AF_INET;
addr_in.sin_port = htons(1004); bind(sock, (PSOCKADDR)&addr_in, sizeof(addr_in));
// dwValue为输入输出参数,为1时执行,0时取消
DWORD dwValue = 1;
// 设置 SOCK_RAW 为SIO_RCVALL,以便接收所有的IP包。其中SIO_RCVALL
// 的定义为: #define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)
ioctlsocket(sock, SIO_RCVALL, &dwValue); //将网卡设置为混合模式  
char RecvBuf[BUFFER_SIZE]; IP ip;
TCP tcp;
UDP udp;
int i=1;
while (true)
{
memset(RecvBuf,0x00,BUFFER_SIZE);
// 接收原始数据包信息
int ret = recv(sock, RecvBuf, BUFFER_SIZE, 0);
if (ret !=0)
{
printf("个数:%d\n",i++);
// 对数据包进行分析,并输出分析结果
ip = *(IP*)RecvBuf;
switch(ip.Protocol)
{
case IPPROTO_TCP:
tcp = *(TCP*)(RecvBuf + ip.HdrLen);
cout<<"IP源地址"<<inet_ntoa(*(in_addr*)&ip.SrcAddr)<<endl;
cout<<"IP目标地址"<<inet_ntoa(*(in_addr*)&ip.DstAddr)<<endl;
cout<<"TCP源端口号"<<tcp.SrcPort<<endl;
cout<<"TCP目标端口号"<<tcp.DstPort<<endl;
cout<<"数据部分长度"<<ntohs(ip.TotalLen)-40<<endl;
break;
case IPPROTO_UDP:
udp = *(UDP*)(RecvBuf + ip.HdrLen);
cout<<"IP源地址"<<inet_ntoa(*(in_addr*)&ip.SrcAddr)<<endl;
cout<<"IP目标地址"<<inet_ntoa(*(in_addr*)&ip.DstAddr)<<endl;
cout<<"UDP源端口号"<<udp.nPortSrc<<endl;
cout<<"UDP目标端口号"<<udp.nPortDst<<endl;
cout<<"数据部分长度"<<ntohs(ip.TotalLen)-40<<endl;
break;
default:printf("\nOTHER\n");
} }
}
}

解决方案 »

  1.   

    这是我原来做原始套接字时定义的IP头
    /* The IP header */
    typedef struct _IPHEADER {
            unsigned char  header_len:4;
            unsigned char  version:4;   
            unsigned char  tos;            // type of service
            unsigned short total_len;      // length of the packet
            unsigned short ident;          // unique identifier
            unsigned short flags;          
            unsigned char  ttl;            
            unsigned char  proto;          // protocol ( IP , TCP, UDP etc)
            unsigned short checksum;       
            unsigned int   sourceIP;
            unsigned int   destIP;}IPHEADER;
      

  2.   

    可是如果我不加bind就收干脆收不到东西啊,我现在试着用位运算做了一下,似乎没什么问题了,感谢大家。