#include <winsock2.h>
#include <ws2tcpip.h>
#include <iostream>
using namespace std;
#pragma comment(lib, "ws2_32.lib")
#define BUFFER_SIZE 1024
#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)
typedef struct _TCP //應用層,傳輸層層
{
WORD SrcPort; // 源端口
WORD 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; // 服務類型
WORD TotalLen; // 總長
WORD ID; // 辨別
union
{
WORD Flags; // 标志
WORD FragOff; // 分段偏移
};
BYTE TimeToLive; // 生命期
BYTE Protocol; // 協定
WORD HdrChksum; // 頭校驗和
DWORD SrcAddr; // 源位址
DWORD DstAddr; // 目的位址
BYTE Options; // 選項
} IP;
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;
}
}
//*.cpp
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);
// 設定IP頭操作選項,其中flag 設定為ture,親自對IP頭進行處理
BOOL flag=TRUE;
setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char*)&flag, sizeof(flag));
// 擷取本機名
char LocalName[512];
gethostname((char*)LocalName, sizeof(LocalName)-1);
// 擷取本地 IP 位址
hostent * pHost;
pHost=gethostbyname((char*)LocalName);
// 填充SOCKADDR_IN結構
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);
// 把原始套接字sock 綁定到本地網卡位址上
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;
while (true)
{
// 接收原始資料包資訊
int ret = recv(sock, RecvBuf, BUFFER_SIZE, 0);
if (ret !=0)
{
// 對資料包進行分析,并輸出分析結果
ip = *(IP*)RecvBuf;
tcp = *(TCP*)(RecvBuf + ip.HdrLen);
cout<<"協定"<<GetProtocolTxt(ip.Protocol)<<endl;
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)<<endl;
//cout<<(char *)(RecvBuf+sizeof(ip)+sizeof(tcp));
//cout<<(char *)(RecvBuf+28)<<endl;
}
}
}
轉自:http://hi.baidu.com/gm123092267/blog/item/93a4583a5de63af8b311c7ce.html