您似乎正在寻找类似于Network Monitor 3 tool 的实现。
你可以从Windows Sockets 2开始学习。如果您想快速完成您的项目,那么您可以专注于以下 API。
socket function、bind function、recvfrom function 等
其中,recvfrom接受的缓冲区就是我们需要的。
recvfrom 函数读取已连接和
未连接的套接字并捕获数据所在的地址
发送。此函数通常与无连接套接字一起使用。
对于面向消息的套接字,数据是从第一个
排队的消息,最大为指定的缓冲区大小。如果
数据报或消息大于指定的缓冲区,缓冲区是
填充数据报的第一部分,recvfrom 生成
错误 WSAEMSGSIZE。对于不可靠的协议(例如,UDP)
多余的数据丢失。对于 UDP,如果接收到的数据包不包含数据
(空),recvfrom函数的返回值为零。
..
当然,我们需要一个合适的例子来帮助我们前进。
一些代码:
typedef struct ip_hdr
{
unsigned char ip_header_len : 4; // 4-bit header length (in 32-bit words) normally=5 (Means 20 Bytes may be 24 also)
unsigned char ip_version : 4; // 4-bit IPv4 version
unsigned char ip_tos; // IP type of service
unsigned short ip_total_length; // Total length
unsigned short ip_id; // Unique identifier
unsigned char ip_frag_offset : 5; // Fragment offset field
unsigned char ip_more_fragment : 1;
unsigned char ip_dont_fragment : 1;
unsigned char ip_reserved_zero : 1;
unsigned char ip_frag_offset1; //fragment offset
unsigned char ip_ttl; // Time to live
unsigned char ip_protocol; // Protocol(TCP,UDP etc)
unsigned short ip_checksum; // IP checksum
unsigned int ip_srcaddr; // Source address
unsigned int ip_destaddr; // Source address
} IPV4_HDR;
typedef struct udp_hdr
{
unsigned short source_port; // Source port no.
unsigned short dest_port; // Dest. port no.
unsigned short udp_length; // Udp packet length
unsigned short udp_checksum; // Udp checksum (optional)
} UDP_HDR;
// TCP header
typedef struct tcp_header
{
unsigned short source_port; // source port
unsigned short dest_port; // destination port
unsigned int sequence; // sequence number - 32 bits
unsigned int acknowledge; // acknowledgement number - 32 bits
unsigned char ns : 1; //Nonce Sum Flag Added in RFC 3540.
unsigned char reserved_part1 : 3; //according to rfc
unsigned char data_offset : 4; /*The number of 32-bit words in the TCP header.
This indicates where the data begins.
The length of the TCP header is always a multiple
of 32 bits.*/
unsigned char fin : 1; //Finish Flag
unsigned char syn : 1; //Synchronise Flag
unsigned char rst : 1; //Reset Flag
unsigned char psh : 1; //Push Flag
unsigned char ack : 1; //Acknowledgement Flag
unsigned char urg : 1; //Urgent Flag
unsigned char ecn : 1; //ECN-Echo Flag
unsigned char cwr : 1; //Congestion Window Reduced Flag
////////////////////////////////
unsigned short window; // window
unsigned short checksum; // checksum
unsigned short urgent_pointer; // urgent pointer
} TCP_HDR;
...
int main()
{
SOCKET sniffer;
struct in_addr addr;
int in;
char hostname[100];
struct hostent* local;
WSADATA wsa;
logfile = fopen("log.txt", "w");
if (logfile == NULL)
{
printf("Unable to create file.");
}
//Initialise Winsock
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("WSAStartup() failed.\n");
return 1;
}
printf("Initialised");
//Create a RAW Socket
printf("\nCreating RAW Socket...");
sniffer = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
if (sniffer == INVALID_SOCKET)
{
printf("Failed to create raw socket.\n");
return 1;
}
printf("Created.");
//Retrive the local hostname
if (gethostname(hostname, sizeof(hostname)) == SOCKET_ERROR)
{
printf("Error : %d", WSAGetLastError());
return 1;
}
printf("\nHost name : %s \n", hostname);
//Retrive the available IPs of the local host
local = gethostbyname(hostname);
printf("\nAvailable Network Interfaces : \n");
if (local == NULL)
{
printf("Error : %d.\n", WSAGetLastError());
return 1;
}
for (i = 0; local->h_addr_list[i] != 0; ++i)
{
memcpy(&addr, local->h_addr_list[i], sizeof(struct in_addr));
printf("Interface Number : %d Address : %s\n", i, inet_ntoa(addr));
}
printf("Enter the interface number you would like to sniff : ");
scanf("%d", &in);
memset(&dest, 0, sizeof(dest));
memcpy(&dest.sin_addr.s_addr, local->h_addr_list[in], sizeof(dest.sin_addr.s_addr));
dest.sin_family = AF_INET;
dest.sin_port = 0;
printf("\nBinding socket to local system and port 0 ...");
if (bind(sniffer, (struct sockaddr*) & dest, sizeof(dest)) == SOCKET_ERROR)
{
printf("bind(%s) failed.\n", inet_ntoa(addr));
return 1;
}
printf("Binding successful");
//Enable this socket with the power to sniff : SIO_RCVALL is the key Receive ALL ;)
j = 1;
printf("\nSetting socket to sniff...");
if (WSAIoctl(sniffer, SIO_RCVALL, &j, sizeof(j), 0, 0, (LPDWORD)&in, 0, 0) == SOCKET_ERROR)
{
printf("WSAIoctl() failed.\n");
return 1;
}
printf("Socket set.");
//Begin
printf("\nStarted Sniffing\n");
printf("Packet Capture Statistics...\n");
StartSniffing(sniffer);
//End
closesocket(sniffer);
WSACleanup();
return 0;
}
完整代码:winsock sample(开箱即用)别忘了以管理员身份运行。
您还可以使用 Network Monitor 3.4 工具来了解缓冲区结构。