计算机网络课程设计——发送和接收TCP数据包以及发送和捕获ARP数据包

本文详细介绍了一种基于TCP协议的程序设计,该程序能够发送和接收TCP数据包,包括填充TCP数据包、发送给目的主机以及在目的主机接收并显示数据字段。文章还深入探讨了如何利用winpcap实现ARP数据包的发送与接收,获取本机MAC地址,以及向局域网内所有主机发送ARP请求,获取其MAC地址。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.课程设计要求:

发送和接收TCP数据包:TCP是一种面向连接的、可靠的传输层协议。TCP协议工作在网络层IP协议的基础上。本课程设计的目的是设计一个发送和接收TCP数据包的程序,其功能是填充一个TCP数据包,发送给目的主机,并在目的主机接收此TCP数据包,将数据字段显示在标准输出上。

2.设计原理

TCP位于IP层之上,应用层之下的传输层。不同主机的应用层之间经常需要可靠的、像管道一样的连接。而面向连接、提供可靠传输的TCP协议则正好能够满足这一需求。因此被广泛利用。ARP的发送和接收数据包利用winpcap实现编程,先获得本机设备列表,然后打开选中的适配器进行抓包,并获取获取IP和子网掩码,通过对ARP和以太网的首部进行填充来构建一个ARP请求报文,然后再将其捕获并解析,来获得本机的MAC物理地址。当于构造了一个外来的ARP请求,本机捕获到了请求,然后发送回应给对方的数据包也被本机捕获到了并解析出来了,解析了自己发出去的数据包。获取到了自身的MAC地址之后,就可以在本机上构建ARP广播请求,向局域网内的所有主机发送ARP请求,得到回应之后接收回应的数据包并进行解析,得到对方的MAC地址。
接下来进行发送和接收TCP数据包,让用户输入要发送的IP地址和要发送的数据,然后需要声明各种结构体,我们发送的是TCP数据,这样,TCP的TcpData 就作为真正的内容,然后在前面加上TCP头,IP头,帧头,还有校验和要正确,对各种结构体的数据进行初始化赋值,并计算校验和。最后构成一个完整的帧。使用winpcap中自带的pcap_sendpacket()函数将其发送出去,编写接收TCP程序,将其接收并解析出来。

3.主程序流程图

(1)发送和捕获ARP数据包流程图:

在这里插入图片描述

(2)发送和接收TCP数据包流程图:

在这里插入图片描述

4.核心代码:

1)发送和捕获ARP数据包:

①构建APR请求报文并自己捕获,获得主机的MAC地址:

// 获取自己主机的MAC地址
int GetSelfMac(pcap_t *adhandle, const char *ip_addr, unsigned char *ip_mac) {
	unsigned char sendbuf[42]; //arp包结构大小
	int i = -1;
	int res;
	EthernetHeader eh; //以太网帧头
	Arpheader ah;  //ARP帧头
	struct pcap_pkthdr * pkt_header;
	const u_char * pkt_data;
	//将已开辟内存空间 eh.dest_mac_add 的首 6个字节的值设为值 0xff。
	memset(eh.DestMAC, 0xff, 6); //目的地址为全为广播地址
	memset(eh.SourMAC, 0x0f, 6);
	memset(ah.DestMacAdd, 0x0f, 6);
	memset(ah.SourceMacAdd, 0x00, 6);
	//htons将一个无符号短整型的主机数值转换为网络字节顺序
	eh.EthType = htons(ETH_ARP);
	ah.HardwareType= htons(ARP_HARDWARE);
	ah.ProtocolType = htons(ETH_IP);
	ah.HardwareAddLen = 6;
	ah.ProtocolAddLen = 4;
	ah.SourceIpAdd = inet_addr("100.100.100.100"); //随便设的请求方ip
	ah.OperationField = htons(ARP_REQUEST);
	ah.DestIpAdd = inet_addr(ip_addr);

	memset(sendbuf, 0, sizeof(sendbuf));
	memcpy(sendbuf, &eh, sizeof(eh));
	memcpy(sendbuf + sizeof(eh), &ah, sizeof(ah));
	printf("%s",sendbuf);
	if (pcap_sendpacket(adhandle, sendbuf, 42) == 0) {
		printf("\nPacketSend succeed\n");
	} else {
		printf("PacketSendPacket in getmine Error: %d\n", GetLastError());
		return 0;
	}
	//从interface或离线记录文件获取一个报文
	//pcap_next_ex(pcap_t* p,struct pcap_pkthdr** pkt_header,const u_char** pkt_data)
	while ((res = pcap_next_ex(adhandle, &pkt_header, &pkt_data)) >= 0) {
		if (*(unsigned short *) (pkt_data + 12) == htons(ETH_ARP)
				&& *(unsigned short*) (pkt_data + 20) == htons(ARP_REPLY)
				&& *(unsigned long*) (pkt_data + 38)
						== inet_addr("100.100.100.100")) {
			for (i = 0; i < 6; i++) {
				ip_mac[i] = *(unsigned char *) (pkt_data + 22 + i);
			}
			printf("获取自己主机的MAC地址成功!\n");
			break;
		}
	}
	if (i == 6) {
		return 1;
	} else {
		return 0;
	}
}
	

②向局域网内所有可能的IP地址发送ARP请求包线程:

DWORD WINAPI SendArpPacket(LPVOID lpParameter) //(pcap_t *adhandle,char *ip,unsigned char *mac,char *netmask)
{
	sparam *spara = (sparam *) lpParameter;
	pcap_t *adhandle = spara->adhandle;
	char *ip = spara->ip;
	unsigned char *mac = spara->mac;
	char *netmask = spara->netmask;
	printf("ip_mac:%02x-%02x-%02x-%02x-%02x-%02x\n", mac[0], mac[1], mac[2],
			mac[3], mac[4], mac[5]);
	printf("自身的IP地址为:%s\n", ip);
	printf("地址掩码NETMASK为:%s\n", netmask);
	printf("\n");
	unsigned char sendbuf[42]; //arp包结构大小
	EthernetHeader eh;
	Arpheader ah;
	//赋值MAC地址
	memset(eh.DestMAC, 0xff, 6);       //目的地址为全为广播地址
	memcpy(eh.SourMAC, mac, 6);
	memcpy(ah.SourceMacAdd, mac, 6);
	memset(ah.DestMacAdd, 0x00, 6);
	eh.EthType = htons(ETH_ARP);
	ah.HardwareType = htons(ARP_HARDWARE);
	ah.ProtocolType = htons(ETH_IP);
	ah.HardwareAddLen = 6;
	ah.ProtocolAddLen = 4;
	ah.SourceIpAdd = inet_addr(ip); //请求方的IP地址为自身的IP地址
	ah.OperationField = htons(ARP_REQUEST);
	//向局域网内广播发送arp包
	unsigned long myip = inet_addr(ip);
	unsigned long mynetmask = inet_addr(netmask);
	unsigned long hisip = htonl((myip & mynetmask));
	//向255个主机发送
	for (int i = 0; i < HOSTNUM; i++) {
		ah.DestIpAdd = htonl(hisip + i);
		//构造一个ARP请求
		memset(sendbuf, 0, sizeof(sendbuf));
		memcpy(sendbuf, &eh, sizeof(eh));
		memcpy(sendbuf + sizeof(eh), &ah, sizeof(ah));
		//如果发送成功
		if (pcap_sendpacket(adhandle, sendbuf, 42) == 0) {
		//	printf("\nPacketSend succeed1\n");
		} else {
			printf("PacketSendPacket in getmine Error: %d\n", GetLastError());
		}
		Sleep(50);
	}
	Sleep(1000);
	flag = TRUE;
	return 0;
}

③分析截留的数据包获取活动的主机IP地址

DWORD WINAPI GetLivePC(LPVOID lpParameter) //(pcap_t *adhandle)
{
	gparam *gpara = (gparam *) lpParameter;
	pcap_t *adhandle = gpara->adhandle;
	int res;
	unsigned char Mac[6];
	struct pcap_pkthdr * pkt_header;
	const u_char * pkt_data;
	while (true) {
		if (flag) {
			printf("获取MAC地址完毕,请输入你要发送对方的IP地址:\n");
			break;
		}
		if ((res = pcap_next_ex(adhandle, &pkt_header, &pkt_data)) >= 0) {
			if (*(unsigned short *) (pkt_data + 12) == htons(ETH_ARP)) {
				ArpPacket *recv = (ArpPacket *) pkt_data;
				if (*(unsigned short *) (pkt_data + 20) == htons(ARP_REPLY)) {
					printf("-------------------------------------------\n");
					printf("IP地址:%d.%d.%d.%d   MAC地址:",
						     recv->ah.SourceIpAdd & 255,
							 recv->ah.SourceIpAdd >> 8 & 255,
							 recv->ah.SourceIpAdd >> 16 & 255,
							 recv->ah.SourceIpAdd >> 24 & 255);
					for (int i = 0; i < 6; i++) {
						Mac[i] = *(unsigned char *) (pkt_data + 22 + i);
						printf("%02x", Mac[i]);
					}
					printf("\n");
				}
			}
		}
		Sleep(10);
	}
	return 0;
}

2)发送和捕获ARP数据包:

①初始化TCP发送数据包并将其发送出去:

//结构体初始化为0序列
		memset(&ethernet, 0, sizeof(ethernet));
		BYTE destmac[8];
		destmac[0] = 0x00;
		destmac[1] = 0x11;
		destmac[2] = 0x22;
		destmac[3] = 0x33;
		destmac[4] = 0x44;
		destmac[5] = 0x55;
		//赋值目的MAC地址
		memcpy(ethernet.DestMAC, destmac, 6);
		BYTE hostmac[8];
		//源MAC地址
		hostmac[0] = 0x00;
		hostmac[1] = 0x1a;
		hostmac[2] = 0x4d;
		hostmac[3] = 0x70;
		hostmac[4] = 0xa3;
		hostmac[5] = 0x89;
		//赋值源MAC地址
		memcpy(ethernet.SourMAC, hostmac, 6);
		//上层协议类型,0x0800代表IP协议
		ethernet.EthType = htons(0x0800);
		//赋值SendBuffer
		memcpy(&SendBuffer, &ethernet, sizeof(struct EthernetHeader));
		//赋值IP头部信息
		ip.Version_HLen = 0x45;
		ip.TOS = 0;
		ip.Length = htons(sizeof(struct IpHeader) + sizeof(struct TcpHeader) + strlen(TcpData));
		ip.Ident = htons(1);
		ip.Flags_Offset = 0;
		ip.TTL = 128;
		ip.Protocol = 6;
		ip.Checksum = 0;
		//源IP地址
		ip.SourceAddr.byte1 = 127;
		ip.SourceAddr.byte2 = 0;
		ip.SourceAddr.byte3 = 0;
		ip.SourceAddr.byte4 = 1;
		//目的IP地址
		ip.DestinationAddr.byte1 = ip1;
		ip.DestinationAddr.byte2 = ip2;
		ip.DestinationAddr.byte3 = ip3;
		ip.DestinationAddr.byte4 = ip4;
		//赋值SendBuffer
		memcpy(&SendBuffer[sizeof(struct EthernetHeader)], &ip, 20);
		//赋值TCP头部内容
		tcp.DstPort = htons(102);
		tcp.SrcPort = htons(1000);
		tcp.SequenceNum = htonl(11);
		tcp.Acknowledgment = 0;
		tcp.HdrLen = 0x50;
		tcp.Flags = 0x18;
		tcp.AdvertisedWindow = htons(512);
		tcp.UrgPtr = 0;
		tcp.Checksum = 0;
		//赋值SendBuffer
		memcpy(&SendBuffer[sizeof(struct EthernetHeader) + 20], &tcp, 20);
		//赋值伪首部
		ptcp.SourceAddr = ip.SourceAddr;
		ptcp.DestinationAddr = ip.DestinationAddr;
		ptcp.Zero = 0;
		ptcp.Protcol = 6;
		ptcp.TcpLen = htons(sizeof(struct TcpHeader) + strlen(TcpData));
		//声明临时存储变量,用来计算校验和
		char TempBuffer[65535];
		memcpy(TempBuffer, &ptcp, sizeof(struct PsdTcpHeader));
		memcpy(TempBuffer + sizeof(struct PsdTcpHeader), &tcp, sizeof(struct TcpHeader));
		memcpy(TempBuffer + sizeof(struct PsdTcpHeader) + sizeof(struct TcpHeader), TcpData, strlen(TcpData));
		//计算TCP的校验和
		tcp.Checksum = checksum((USHORT*)(TempBuffer), sizeof(struct PsdTcpHeader) + sizeof(struct TcpHeader) + strlen(TcpData));
		//重新把SendBuffer赋值,因为此时校验和已经改变,赋值新的
		memcpy(SendBuffer + sizeof(struct EthernetHeader) + sizeof(struct IpHeader), &tcp, sizeof(struct TcpHeader));
		memcpy(SendBuffer + sizeof(struct EthernetHeader) + sizeof(struct IpHeader) + sizeof(struct TcpHeader), TcpData, strlen(TcpData));
		//初始化TempBuffer为0序列,存储变量来计算IP校验和
		memset(TempBuffer, 0, sizeof(TempBuffer));
		memcpy(TempBuffer, &ip, sizeof(struct IpHeader));
		//计算IP校验和
		ip.Checksum = checksum((USHORT*)(TempBuffer), sizeof(struct IpHeader));
		//重新把SendBuffer赋值,IP校验和已经改变
		memcpy(SendBuffer + sizeof(struct EthernetHeader), &ip, sizeof(struct IpHeader));
		//发送序列的长度
		int size = sizeof(struct EthernetHeader) + sizeof(struct IpHeader) + sizeof(struct TcpHeader) + strlen(TcpData);
		int result = pcap_sendpacket(adhandle, SendBuffer,size);
		if (result != 0)
		{
			printf("Send Error!\n");
		} 
		else
		{
			printf("发送TCP数据包.\n");
			printf("目的端口:%d\n", ntohs(tcp.DstPort));
			printf("源端口:%d\n", ntohs(tcp.SrcPort));
			printf("序号:%d\n", ntohl(tcp.SequenceNum));
			printf("确认号:%d\n", ntohl(tcp.Acknowledgment));
			printf("首部长度:%d*4\n", tcp.HdrLen >> 4);
			printf("标志位:0x%0x\n", ntohs(tcp.Flags));
			printf("窗口大小:%d\n", ntohs(tcp.AdvertisedWindow));
			printf("紧急指针:%d\n", ntohs(tcp.UrgPtr));
			printf("检验和:%u\n", ntohs(tcp.Checksum));
			printf("发送成功!\n");
		}
		free(TcpData);
		}

	return 0}

②捕获TCP数据包并将数据内容显示出来:

void ip_protool_packet_callback(u_char *argument,const struct pcap_pkthdr* packet_header,const u_char* packet_content)
{
  struct ip_header *ip_protocol;
  u_int header_length = 0;
  u_int offset;
  u_char tos;
  u_int16_t checksum;
  u_int ip_len;                      //ip首部长度
  u_int ip_version;  
  TcpHeader *tcp;                  //TCP头
  u_short sport,dport;            
  //MAC首部是14位的,加上14位得到IP协议首部
  ip_protocol = (struct ip_header *) (packet_content+14);
  ip_len = (ip_protocol->Version_HLen & 0xf) *4;
  ip_version = ip_protocol->Version_HLen>>4;
  tcp = (TcpHeader *)((u_char *)ip_protocol+ip_len);
  checksum =ntohs(ip_protocol->ip_checksum);
  tos = ip_protocol->ip_tos;
  offset = ntohs(ip_protocol->ip_off);
  if(*(unsigned long*)(packet_content+30)==inet_addr("100.100.100.100")){//如果接收端ip地址为100.100.100.100
  printf("检验和:%d\n",checksum);
  printf("源IP地址:%s\n", inet_ntoa(ip_protocol->ip_souce_address));
  printf("目的地址:%s\n", inet_ntoa(ip_protocol->ip_destination_address));
  		
   //将网络字节序列转换成主机字节序列
	printf("---------TCP协议---------\n");
			sport = ntohs( tcp->SrcPort );
			dport = ntohs( tcp->DstPort );
			printf("源端口:%d 目的端口:%d\n",sport,dport);
            printf("序号:%d\n",ntohl(tcp->SequenceNum));
			printf("确认号:%d\n",ntohl(tcp->Acknowledgment));
			printf("偏移地址(首部长度):%d\n",(tcp->HdrLen>>4)*4);
			printf("标志位:%d\n",tcp->Flags);
			printf("紧急UGR:%d\n",(tcp->Flags & 0x20)/32);
			printf("确认ACK:%d\n",(tcp->Flags & 0x10)/16);
			printf("推送PSH:%d\n",(tcp->Flags & 0x08)/8);
			printf("复位RST:%d\n",(tcp->Flags & 0x04)/4);
			printf("同步SYN:%d\n",(tcp->Flags & 0x02)/2);
			printf("终止FIN:%d\n",tcp->Flags & 0x01);
			printf("窗口大小:%d\n",ntohs(tcp->AdvertisedWindow));
			printf("校验和:%d\n",ntohs(tcp->Checksum));
			printf("紧急指针:%d\n",ntohs(tcp->UrgPtr));
			char * data;
			data = (char *)((u_char *)tcp+20);
			printf("---------数据部分---------\n");
			printf("数据部分:%s\n",data);

  }
}

5.结果及分析

1、运行结果:

获得本地网卡并选择适配器:

在这里插入图片描述

发送ARP请求报文并将其捕获,获取本地MAC地址:

在这里插入图片描述

在本机上构建ARP广播请求,向局域网内的所有主机发送ARP请求,得到回应之后解析回应的数据包并进行解析,得到本局域网内所有的MAC地址:

在这里插入图片描述

输入要发送的IP地址和数据内容,发送成功:

在这里插入图片描述

在接收程序端捕获该数据报内容并显示出来:

在这里插入图片描述

2.分析

通过观察实验结果可以发现发送ARP请求报文并被自己捕获到后得到了正确的本机MAC地址,在本机上构建ARP广播请求,向局域网内的所有主机发送ARP请求,得到回应之后解析回应的数据包并进行解析,得到本局域网内所有的MAC地址。在发送端输入要发送的IP地址和数据内容后TCP报文发送成功,并可在接收端显示出来,成功达到实验目的。

6.完整代码如下:

6.1发送与接收ARP包发送TCP数据

#include <stdio.h>
#include <stdlib.h>
#include <pcap.h>
#define ETH_ARP         0x0806  //以太网帧类型表示后面数据的类型,对于ARP请求或应答来说,该字段的值为x0806
#define ARP_HARDWARE    1  //硬件类型字段值为表示以太网地址
#define ETH_IP          0x0800  //协议类型字段表示要映射的协议地址类型值为x0800表示IP地址
#define ARP_REQUEST     1   //ARP请求
#define ARP_REPLY       2      //ARP应答
#define HOSTNUM         255   //主机数量
char *iptos(u_long in);       //u_long即为 unsigned long
void ifget(pcap_if_t *d, char *ip_addr, char *ip_netmask);   //用ifget方法获取自身的IP和子网掩码
int GetSelfMac(pcap_t *adhandle, const char *ip_addr, unsigned char *ip_mac);//发送一个ARP请求来获取自身的MAC地址
unsigned short checksum(unsigned short *data, int length);//校验和方法
DWORD WINAPI SendArpPacket(LPVOID lpParameter);
DWORD WINAPI GetLivePC(LPVOID lpParameter) ;
bool flag;
//声明两个线程
	HANDLE sendthread;      //发送ARP包线程
	HANDLE recvthread;       //接受ARP包线程
#pragma pack(1)  //按一个字节内存对齐
//帧头部结构体,共14字节
struct EthernetHeader
{
    u_char DestMAC[6];    //目的MAC地址 6字节
    u_char SourMAC[6];   //源MAC地址 6字节
    u_short EthType;         //上一层协议类型,如0x0800代表上一层是IP协议,0x0806为arp  2字节
};
 
//28字节ARP帧结构
struct Arpheader {
	unsigned short HardwareType; //硬件类型
	unsigned short ProtocolType; //协议类型
	unsigned char HardwareAddLen; //硬件地址长度
	unsigned char ProtocolAddLen; //协议地址长度
	unsigned short OperationField; //操作字段
	unsigned char SourceMacAdd[6]; //源mac地址
	unsigned long SourceIpAdd; //源ip地址
	unsigned char DestMacAdd[6]; //目的mac地址
	unsigned long DestIpAdd; //目的ip地址
};
 
//arp包结构
struct ArpPacket {
	EthernetHeader ed;
	Arpheader ah;
};
 
struct sparam {
	pcap_t *adhandle;
	char *ip;
	unsigned char *mac;
	char *netmask;
};
struct gparam {
	pcap_t *adhandle;
};
 
struct sparam sp;
struct gparam gp;
//IP地址格式
struct IpAddress
{
    u_char byte1;
    u_char byte2;
    u_char byte3;
    u_char byte4;
};
 
//IP头部结构体,共20字节
struct IpHeader
{
    unsigned char Version_HLen;   //版本信息4位 ,头长度4位 1字节
    unsigned char TOS;                    //服务类型    1字节
    short Length;                              //数据包长度 2字节
    short Ident;                                 //数据包标识  2字节
    short Flags_Offset;                    //标志3位,片偏移13位  2字节
    unsigned char TTL;                   //存活时间  1字节
    unsigned char Protocol;          //协议类型  1字节
    short Checksum;                       //首部校验和 2字节
	IpAddress SourceAddr;       //源IP地址   4字节
	IpAddress DestinationAddr; //目的IP地址  4字节
};
 
//TCP头部结构体,共20字节
struct TcpHeader
{
    unsigned short SrcPort;                        //源端口号  2字节
    unsigned short DstPort;                        //目的端口号 2字节
    unsigned int SequenceNum;               //序号  4字节
    unsigned int Acknowledgment;         //确认号  4字节
    unsigned char HdrLen;                         //首部长度4位,保留位6位 共10位
    unsigned char Flags;                              //标志位6位
    unsigned short AdvertisedWindow;  //窗口大小16位 2字节
    unsigned short Checksum;                  //校验和16位   2字节
    unsigned short UrgPtr;						  //紧急指针16位   2字节
};
 
//TCP伪首部结构体 12字节
struct PsdTcpHeader
{
	IpAddress SourceAddr;                     //源IP地址  4字节
	IpAddress DestinationAddr;             //目的IP地址 4字节
    char Zero;                                                    //填充位  1字节
    char Protcol;                                               //协议号  1字节
    unsigned short TcpLen;                           //TCP包长度 2字节
};
int main(){
	char *ip_addr;                   //IP地址
	char *ip_netmask;                //子网掩码
	unsigned char *ip_mac;          //本机MAC地址
	/* 为这三个变量分配地址空间*/
	ip_addr = (char *) malloc(sizeof(char) * 16); //申请内存存放IP地址
	if (ip_addr == NULL)
	{
		printf("申请内存存放IP地址失败!\n");
		return -1;
	}
	ip_netmask = (char *) malloc(sizeof(char) * 16); //申请内存存放NETMASK地址
	if (ip_netmask == NULL)
	{
		printf("申请内存存放NETMASK地址失败!\n");
		return -1;
	}
	ip_mac = (unsigned char *) malloc(sizeof(unsigned char) * 6); //申请内存存放MAC地址
	if (ip_mac == NULL)
	{
		printf("申请内存存放MAC地址失败!\n");
		return -1;
	}
	pcap_if_t  * alldevs;       //所有网络适配器
	pcap_if_t  *d;					//选中的网络适配器
	char errbuf[PCAP_ERRBUF_SIZE];   //错误缓冲区,大小为256
	pcap_t *adhandle;           //捕捉实例,是pcap_open返回的对象
	int i = 0;                            //适配器计数变量
	/* 获取适配器列表并选中相应的适配器,*/
	//获取本地适配器列表
	if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING,NULL,&alldevs,errbuf) == -1){
		//结果为-1代表出现获取适配器列表失败
		fprintf(stderr,"Error in pcap_findalldevs_ex:\n",errbuf);
		//exit(0)代表正常退出,exit(other)为非正常退出,这个值会传给操作系统
		exit(1);
	}
	
 
	for(d = alldevs;d !=NULL;d = d->next){
		printf("-----------------------------------------------------------------\nnumber:%d\nname:%s\n",++i,d->name);
		if(d->description){
			//打印适配器的描述信息
			printf("description:%s\n",d->description);
		}else{
			//适配器不存在描述信息
			printf("description:%s","no description\n");
		}
		//打印本地环回地址
		 printf("\tLoopback: %s\n",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no");
		 /**
		 pcap_addr *  next     指向下一个地址的指针
		 sockaddr *  addr       IP地址
		 sockaddr *  netmask  子网掩码
		 sockaddr *  broadaddr   广播地址
		 sockaddr *  dstaddr        目的地址
		 */
		 pcap_addr_t *a;       //网络适配器的地址用来存储变量
		 for(a = d->addresses;a;a = a->next){
			 //sa_family代表了地址的类型,是IPV4地址类型还是IPV6地址类型
			 switch (a->addr->sa_family)
			 {
				 case AF_INET:  //代表IPV4类型地址
					 printf("Address Family Name:AF_INET\n");
					 if(a->addr){
						 //->的优先级等同于括号,高于强制类型转换,因为addr为sockaddr类型,对其进行操作须转换为sockaddr_in类型
						 printf("Address:%s\n",iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr));
					 }
					if (a->netmask){
						 printf("\tNetmask: %s\n",iptos(((struct sockaddr_in *)a->netmask)->sin_addr.s_addr));
					}
					if (a->broadaddr){
						   printf("\tBroadcast Address: %s\n",iptos(((struct sockaddr_in *)a->broadaddr)->sin_addr.s_addr));
					 }
					 if (a->dstaddr){
						   printf("\tDestination Address: %s\n",iptos(((struct sockaddr_in *)a->dstaddr)->sin_addr.s_addr));
					 }
        			 break;
				 case AF_INET6: //代表IPV6类型地址
					 printf("Address Family Name:AF_INET6\n");
					 printf("this is an IPV6 address\n");
					 break;
				 default:
					 break;
			 }
		 }
	}
	//i为0代表上述循环未进入,即没有找到适配器,可能的原因为Winpcap没有安装导致未扫描到
	if(i == 0){
		printf("interface not found,please check winpcap installation");
	}
 
	int num;
	printf("Enter the interface number(1-%d):",i);
	//让用户选择选择哪个适配器进行抓包
	scanf("%d",&num);
	printf("\n");
 
	//用户输入的数字超出合理范围
	if(num<1||num>i){
		printf("number out of range\n");
		pcap_freealldevs(alldevs);
		return -1;
	}
	//跳转到选中的适配器
	for(d=alldevs, i=0; i< num-1 ; d=d->next, i++);
 
	//运行到此处说明用户的输入是合法的
	if((adhandle = pcap_open(d->name,		//设备名称
		65535,       //存放数据包的内容长度
		PCAP_OPENFLAG_PROMISCUOUS,  //混杂模式
		1000,           //超时时间
		NULL,          //远程验证
		errbuf         //错误缓冲
		)) == NULL){
        //打开适配器失败,打印错误并释放适配器列表
		fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
        // 释放设备列表 
        pcap_freealldevs(alldevs);
        return -1;
	}
	/*对sp和gp两个ARP请求所需要的结构体进行赋值 */
	ifget(d, ip_addr, ip_netmask); //获取所选网卡的基本信息--掩码--IP地址

    GetSelfMac(adhandle,ip_addr,ip_mac);

	sp.adhandle = adhandle;
	sp.ip = ip_addr;
	sp.mac = ip_mac;
	sp.netmask = ip_netmask;
	gp.adhandle = adhandle;
	/*直接创建两个线程,一个是发送一个接受,分别调用两个方法*/
	sendthread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) SendArpPacket,
			&sp, 0, NULL);
	recvthread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) GetLivePC, &gp,
			0, NULL);
	printf("\nlistening on 网卡%d ...\n", i);
	pcap_freealldevs(alldevs);
	getchar();
	getchar();

	while(true){
	char *TcpData;   //发送内容
	TcpData= (char *) malloc(sizeof(char) * 50); //申请内存存放NETMASK地址
	if (TcpData== NULL)
	{
		printf("申请内存存放NETMASK地址失败!\n");
		return -1;
	}
	struct EthernetHeader ethernet;    //以太网帧头
    struct IpHeader ip;                //IP头
    struct TcpHeader tcp;              //TCP头
    struct PsdTcpHeader ptcp;          //TCP伪首部
	unsigned char SendBuffer[200];     //发送队列
	u_int ip1,ip2,ip3,ip4;
		scanf("%d.%d.%d.%d",&ip1,&ip2,&ip3,&ip4);
		printf("请输入你要发送的内容:\n");
		getchar();
		gets(TcpData);
		printf("要发送的内容:%s\n",TcpData);

		//结构体初始化为0序列
		memset(&ethernet, 0, sizeof(ethernet));
		BYTE destmac[8];
		//目的MAC地址,此处没有对帧的MAC地址进行赋值,因为网卡设置的混杂模式,可以接受经过该网卡的所有帧。
		//当然最好的方法是赋值为ARP刚才获取到的MAC地址,当然不赋值也可以捕捉到并解析。
		destmac[0] = 0x00;
		destmac[1] = 0x11;
		destmac[2] = 0x22;
		destmac[3] = 0x33;
		destmac[4] = 0x44;
		destmac[5] = 0x55;
		//赋值目的MAC地址
		memcpy(ethernet.DestMAC, destmac, 6);
		BYTE hostmac[8];
		//源MAC地址
		hostmac[0] = 0x00;
		hostmac[1] = 0x1a;
		hostmac[2] = 0x4d;
		hostmac[3] = 0x70;
		hostmac[4] = 0xa3;
		hostmac[5] = 0x89;
		//赋值源MAC地址
		memcpy(ethernet.SourMAC, hostmac, 6);
		//上层协议类型,0x0800代表IP协议
		ethernet.EthType = htons(0x0800);
		//赋值SendBuffer
		memcpy(&SendBuffer, &ethernet, sizeof(struct EthernetHeader));
		//赋值IP头部信息
		ip.Version_HLen = 0x45;
		ip.TOS = 0;
		ip.Length = htons(sizeof(struct IpHeader) + sizeof(struct TcpHeader) + strlen(TcpData));
		ip.Ident = htons(1);
		ip.Flags_Offset = 0;
		ip.TTL = 128;
		ip.Protocol = 6;
		ip.Checksum = 0;
		//源IP地址
		ip.SourceAddr.byte1 = 127;
		ip.SourceAddr.byte2 = 0;
		ip.SourceAddr.byte3 = 0;
		ip.SourceAddr.byte4 = 1;
		//目的IP地址
		ip.DestinationAddr.byte1 = ip1;
		ip.DestinationAddr.byte2 = ip2;
		ip.DestinationAddr.byte3 = ip3;
		ip.DestinationAddr.byte4 = ip4;
		//赋值SendBuffer
		memcpy(&SendBuffer[sizeof(struct EthernetHeader)], &ip, 20);
		//赋值TCP头部内容
		tcp.DstPort = htons(102);
		tcp.SrcPort = htons(1000);
		tcp.SequenceNum = htonl(11);
		tcp.Acknowledgment = 0;
		tcp.HdrLen = 0x50;
		tcp.Flags = 0x18;
		tcp.AdvertisedWindow = htons(512);
		tcp.UrgPtr = 0;
		tcp.Checksum = 0;
		//赋值SendBuffer
		memcpy(&SendBuffer[sizeof(struct EthernetHeader) + 20], &tcp, 20);
		//赋值伪首部
		ptcp.SourceAddr = ip.SourceAddr;
		ptcp.DestinationAddr = ip.DestinationAddr;
		ptcp.Zero = 0;
		ptcp.Protcol = 6;
		ptcp.TcpLen = htons(sizeof(struct TcpHeader) + strlen(TcpData));
		//声明临时存储变量,用来计算校验和
		char TempBuffer[65535];
		memcpy(TempBuffer, &ptcp, sizeof(struct PsdTcpHeader));
		memcpy(TempBuffer + sizeof(struct PsdTcpHeader), &tcp, sizeof(struct TcpHeader));
		memcpy(TempBuffer + sizeof(struct PsdTcpHeader) + sizeof(struct TcpHeader), TcpData, strlen(TcpData));
		//计算TCP的校验和
		tcp.Checksum = checksum((USHORT*)(TempBuffer), sizeof(struct PsdTcpHeader) + sizeof(struct TcpHeader) + strlen(TcpData));
		//重新把SendBuffer赋值,因为此时校验和已经改变,赋值新的
		memcpy(SendBuffer + sizeof(struct EthernetHeader) + sizeof(struct IpHeader), &tcp, sizeof(struct TcpHeader));
		memcpy(SendBuffer + sizeof(struct EthernetHeader) + sizeof(struct IpHeader) + sizeof(struct TcpHeader), TcpData, strlen(TcpData));
		//初始化TempBuffer为0序列,存储变量来计算IP校验和
		memset(TempBuffer, 0, sizeof(TempBuffer));
		memcpy(TempBuffer, &ip, sizeof(struct IpHeader));
		//计算IP校验和
		ip.Checksum = checksum((USHORT*)(TempBuffer), sizeof(struct IpHeader));
		//重新把SendBuffer赋值,IP校验和已经改变
		memcpy(SendBuffer + sizeof(struct EthernetHeader), &ip, sizeof(struct IpHeader));
		//发送序列的长度
		int size = sizeof(struct EthernetHeader) + sizeof(struct IpHeader) + sizeof(struct TcpHeader) + strlen(TcpData);
		int result = pcap_sendpacket(adhandle, SendBuffer,size);
		if (result != 0)
		{
			printf("Send Error!\n");
		} 
		else
		{
			printf("发送TCP数据包.\n");
			printf("目的端口:%d\n", ntohs(tcp.DstPort));
			printf("源端口:%d\n", ntohs(tcp.SrcPort));
			printf("序号:%d\n", ntohl(tcp.SequenceNum));
			printf("确认号:%d\n", ntohl(tcp.Acknowledgment));
			printf("首部长度:%d*4\n", tcp.HdrLen >> 4);
			printf("标志位:0x%0x\n", ntohs(tcp.Flags));
			printf("窗口大小:%d\n", ntohs(tcp.AdvertisedWindow));
			printf("紧急指针:%d\n", ntohs(tcp.UrgPtr));
			printf("检验和:%u\n", ntohs(tcp.Checksum));
			printf("发送成功!\n");
		}
		free(TcpData);
		}

	return 0;

}
/* 将数字类型的IP地址转换成字符串类型的 */
#define IPTOSBUFFERS    12
char *iptos(u_long in)
{
    static char output[IPTOSBUFFERS][3*4+3+1];
    static short which;
    u_char *p;
 
    p = (u_char *)&in;
    which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
    sprintf(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
    return output[which];
}
//获取IP和子网掩码赋值为ip_addr和ip_netmask
void ifget(pcap_if_t *d, char *ip_addr, char *ip_netmask) {
	pcap_addr_t *a;
	//遍历所有的地址,a代表一个pcap_addr
	for (a = d->addresses; a; a = a->next) {
		switch (a->addr->sa_family) {
		case AF_INET:  //sa_family :是2字节的地址家族,一般都是“AF_xxx”的形式。通常用的都是AF_INET。代表IPV4
			if (a->addr) {
				char *ipstr;
				//将地址转化为字符串
				ipstr = iptos(((struct sockaddr_in *) a->addr)->sin_addr.s_addr); //*ip_addr
				printf("ipstr:%s\n",ipstr);
				memcpy(ip_addr, ipstr, 16);//memcpy 函数用于 把资源内存(src所指向的内存区域) 拷贝到目标内存(dest所指向的内存区域);
				                           //拷贝多少个?有一个size变量控制拷贝的字节数;
			}
			if (a->netmask) {
				char *netmaskstr;
				netmaskstr = iptos(((struct sockaddr_in *) a->netmask)->sin_addr.s_addr);
				printf("netmask:%s\n",netmaskstr);
				memcpy(ip_netmask, netmaskstr, 16);
			}
		case AF_INET6:
			break;
		}
	}
}
// 获取自己主机的MAC地址
int GetSelfMac(pcap_t *adhandle, const char *ip_addr, unsigned char *ip_mac) {
	unsigned char sendbuf[42]; //arp包结构大小
	int i = -1;
	int res;
	EthernetHeader eh; //以太网帧头
	Arpheader ah;  //ARP帧头
	struct pcap_pkthdr * pkt_header;
	const u_char * pkt_data;
	//将已开辟内存空间 eh.dest_mac_add 的首 6个字节的值设为值 0xff。
	memset(eh.DestMAC, 0xff, 6); //目的地址为全为广播地址
	memset(eh.SourMAC, 0x0f, 6);
	memset(ah.DestMacAdd, 0x0f, 6);
	memset(ah.SourceMacAdd, 0x00, 6);
	//htons将一个无符号短整型的主机数值转换为网络字节顺序
	eh.EthType = htons(ETH_ARP);
	ah.HardwareType= htons(ARP_HARDWARE);
	ah.ProtocolType = htons(ETH_IP);
	ah.HardwareAddLen = 6;
	ah.ProtocolAddLen = 4;
	ah.SourceIpAdd = inet_addr("100.100.100.100"); //随便设的请求方ip
	ah.OperationField = htons(ARP_REQUEST);
	ah.DestIpAdd = inet_addr(ip_addr);

	memset(sendbuf, 0, sizeof(sendbuf));
	memcpy(sendbuf, &eh, sizeof(eh));
	memcpy(sendbuf + sizeof(eh), &ah, sizeof(ah));
	printf("%s",sendbuf);
	if (pcap_sendpacket(adhandle, sendbuf, 42) == 0) {
		printf("\nPacketSend succeed\n");
	} else {
		printf("PacketSendPacket in getmine Error: %d\n", GetLastError());
		return 0;
	}
	//从interface或离线记录文件获取一个报文
	//pcap_next_ex(pcap_t* p,struct pcap_pkthdr** pkt_header,const u_char** pkt_data)
	while ((res = pcap_next_ex(adhandle, &pkt_header, &pkt_data)) >= 0) {
		if (*(unsigned short *) (pkt_data + 12) == htons(ETH_ARP)
				&& *(unsigned short*) (pkt_data + 20) == htons(ARP_REPLY)
				&& *(unsigned long*) (pkt_data + 38)
						== inet_addr("100.100.100.100")) {
			for (i = 0; i < 6; i++) {
				ip_mac[i] = *(unsigned char *) (pkt_data + 22 + i);
			}
			printf("获取自己主机的MAC地址成功!\n");
			break;
		}
	}
	if (i == 6) {
		return 1;
	} else {
		return 0;
	}
}
/* 向局域网内所有可能的IP地址发送ARP请求包线程 */
DWORD WINAPI SendArpPacket(LPVOID lpParameter) //(pcap_t *adhandle,char *ip,unsigned char *mac,char *netmask)
{
	sparam *spara = (sparam *) lpParameter;
	pcap_t *adhandle = spara->adhandle;
	char *ip = spara->ip;
	unsigned char *mac = spara->mac;
	char *netmask = spara->netmask;
	printf("ip_mac:%02x-%02x-%02x-%02x-%02x-%02x\n", mac[0], mac[1], mac[2],
			mac[3], mac[4], mac[5]);
	printf("自身的IP地址为:%s\n", ip);
	printf("地址掩码NETMASK为:%s\n", netmask);
	printf("\n");
	unsigned char sendbuf[42]; //arp包结构大小
	EthernetHeader eh;
	Arpheader ah;
	//赋值MAC地址
	memset(eh.DestMAC, 0xff, 6);       //目的地址为全为广播地址
	memcpy(eh.SourMAC, mac, 6);
	memcpy(ah.SourceMacAdd, mac, 6);
	memset(ah.DestMacAdd, 0x00, 6);
	eh.EthType = htons(ETH_ARP);
	ah.HardwareType = htons(ARP_HARDWARE);
	ah.ProtocolType = htons(ETH_IP);
	ah.HardwareAddLen = 6;
	ah.ProtocolAddLen = 4;
	ah.SourceIpAdd = inet_addr(ip); //请求方的IP地址为自身的IP地址
	ah.OperationField = htons(ARP_REQUEST);
	//向局域网内广播发送arp包
	unsigned long myip = inet_addr(ip);
	unsigned long mynetmask = inet_addr(netmask);
	unsigned long hisip = htonl((myip & mynetmask));
	//向255个主机发送
	for (int i = 0; i < HOSTNUM; i++) {
		ah.DestIpAdd = htonl(hisip + i);
		//构造一个ARP请求
		memset(sendbuf, 0, sizeof(sendbuf));
		memcpy(sendbuf, &eh, sizeof(eh));
		memcpy(sendbuf + sizeof(eh), &ah, sizeof(ah));
		//如果发送成功
		if (pcap_sendpacket(adhandle, sendbuf, 42) == 0) {
		//	printf("\nPacketSend succeed1\n");
		} else {
			printf("PacketSendPacket in getmine Error: %d\n", GetLastError());
		}
		Sleep(50);
	}
	Sleep(1000);
	flag = TRUE;
	return 0;
}
/* 分析截留的数据包获取活动的主机IP地址 */
DWORD WINAPI GetLivePC(LPVOID lpParameter) //(pcap_t *adhandle)
{
	gparam *gpara = (gparam *) lpParameter;
	pcap_t *adhandle = gpara->adhandle;
	int res;
	unsigned char Mac[6];
	struct pcap_pkthdr * pkt_header;
	const u_char * pkt_data;
	while (true) {
		if (flag) {
			printf("获取MAC地址完毕,请输入你要发送对方的IP地址:\n");
			break;
		}
		if ((res = pcap_next_ex(adhandle, &pkt_header, &pkt_data)) >= 0) {
			if (*(unsigned short *) (pkt_data + 12) == htons(ETH_ARP)) {
				ArpPacket *recv = (ArpPacket *) pkt_data;
				if (*(unsigned short *) (pkt_data + 20) == htons(ARP_REPLY)) {
					printf("-------------------------------------------\n");
					printf("IP地址:%d.%d.%d.%d   MAC地址:",
						     recv->ah.SourceIpAdd & 255,
							 recv->ah.SourceIpAdd >> 8 & 255,
							 recv->ah.SourceIpAdd >> 16 & 255,
							 recv->ah.SourceIpAdd >> 24 & 255);
					for (int i = 0; i < 6; i++) {
						Mac[i] = *(unsigned char *) (pkt_data + 22 + i);
						printf("%02x", Mac[i]);
					}
					printf("\n");
				}
			}
		}
		Sleep(10);
	}
	return 0;
}
//获得校验和的方法
unsigned short checksum(unsigned short *data, int length)
{
    unsigned long temp = 0;
    while (length > 1)
    {
        temp +=  *data++;
        length -= sizeof(unsigned short);
    }
    if (length)
    {
        temp += *(unsigned short*)data;
    }
    temp = (temp >> 16) + (temp &0xffff);
    temp += (temp >> 16);
    return (unsigned short)(~temp);
}

6.2 接收TCP数据包

//捕获网络数据包的C++程序
//可以获得数据包长度、通过以太网类型确定上层协议、源以太网地址和目的以太网地址!
#include "pcap.h"
#include<winsock2.h>
 
#pragma comment(lib,"wpcap.lib")
#pragma comment(lib,"packet.lib")
#pragma comment(lib,"ws2_32.lib")
void packet_handler(u_char *param,const struct pcap_pkthdr *header,const u_char *pcap_data);
#define IPTOSBUFFERS 12
void ifprint(pcap_if_t *d);
char * iptos(u_long in);
int i = 0;
/*以下是以太网协议格式*/
struct ether_header
{
  u_int8_t ether_dhost[6]; //目的Mac地址
  u_int8_t ether_shost[6]; //源Mac地址
  u_int16_t ether_type;    //协议类型
};
 
struct ip_header
{
unsigned char Version_HLen;   //版本信息4位 ,头长度4位 1字节
  u_int8_t    ip_tos;
  u_int16_t   ip_length;
  u_int16_t   ip_id;
  u_int16_t   ip_off;
  u_int8_t    ip_ttl;
  u_int8_t    ip_protocol;
  u_int16_t   ip_checksum;
  struct in_addr ip_souce_address;
  struct in_addr ip_destination_address;
};
 
//TCP头部结构体,共20字节
struct TcpHeader
{
    unsigned short SrcPort;                        //源端口号  2字节
    unsigned short DstPort;                        //目的端口号 2字节
    unsigned int SequenceNum;               //序号  4字节
    unsigned int Acknowledgment;         //确认号  4字节
    unsigned char HdrLen;                         //首部长度4位,保留位6位 共10位
    unsigned char Flags;                          //标志位6位
    unsigned short AdvertisedWindow;  //窗口大小16位 2字节
    unsigned short Checksum;                  //校验和16位   2字节
    unsigned short UrgPtr;						  //紧急指针16位   2字节
};
 
void ip_protool_packet_callback(u_char *argument,const struct pcap_pkthdr* packet_header,const u_char* packet_content)
{
  struct ip_header *ip_protocol;
  u_int header_length = 0;
  u_int offset;
  u_char tos;
  u_int16_t checksum;
  u_int ip_len;                      //ip首部长度
  u_int ip_version;  
  TcpHeader *tcp;                  //TCP头
  u_short sport,dport;            
  //MAC首部是14位的,加上14位得到IP协议首部
  ip_protocol = (struct ip_header *) (packet_content+14);
  
  ip_len = (ip_protocol->Version_HLen & 0xf) *4;
  ip_version = ip_protocol->Version_HLen>>4;
  tcp = (TcpHeader *)((u_char *)ip_protocol+ip_len);

  checksum =ntohs(ip_protocol->ip_checksum);
  tos = ip_protocol->ip_tos;
  offset = ntohs(ip_protocol->ip_off);
 /*将if判断去掉,即可接受所有TCP数据包 */
  if(*(unsigned long*)(packet_content+30)==inet_addr("100.100.100.100")){//如果接收端ip地址为100.100.100.100
  printf("---------IP协议---------\n");
  printf("版本号:%d\n", ip_version);
  printf("首部长度:%d\n",ip_len);
  printf("服务质量:%d\n",tos);
  printf("总长度:%d\n",ntohs(ip_protocol->ip_length));
  printf("标识:%d\n",ntohs(ip_protocol->ip_id));
  printf("偏移:%d\n",(offset & 0x1fff) * 8);
  printf("生存时间:%d\n",ip_protocol->ip_ttl);
  printf("协议类型:%d\n",ip_protocol->ip_protocol);
  switch (ip_protocol->ip_protocol)
  {
       case 1: printf("上层协议是ICMP协议\n");break;
       case 2: printf("上层协议是IGMP协议\n");break;
       case 6: printf("上层协议是TCP协议\n");break;
       case 17: printf("上层协议是UDP协议\n");break;
       default:break;
  }

  printf("检验和:%d\n",checksum);
  printf("源IP地址:%s\n", inet_ntoa(ip_protocol->ip_souce_address));
  printf("目的地址:%s\n", inet_ntoa(ip_protocol->ip_destination_address));
  		
   //将网络字节序列转换成主机字节序列
	printf("---------TCP协议---------\n");
			sport = ntohs( tcp->SrcPort );
			dport = ntohs( tcp->DstPort );
			printf("源端口:%d 目的端口:%d\n",sport,dport);
            printf("序号:%d\n",ntohl(tcp->SequenceNum));
			printf("确认号:%d\n",ntohl(tcp->Acknowledgment));
			printf("偏移地址(首部长度):%d\n",(tcp->HdrLen>>4)*4);
			printf("标志位:%d\n",tcp->Flags);
			printf("紧急UGR:%d\n",(tcp->Flags & 0x20)/32);
			printf("确认ACK:%d\n",(tcp->Flags & 0x10)/16);
			printf("推送PSH:%d\n",(tcp->Flags & 0x08)/8);
			printf("复位RST:%d\n",(tcp->Flags & 0x04)/4);
			printf("同步SYN:%d\n",(tcp->Flags & 0x02)/2);
			printf("终止FIN:%d\n",tcp->Flags & 0x01);
			printf("窗口大小:%d\n",ntohs(tcp->AdvertisedWindow));
			printf("校验和:%d\n",ntohs(tcp->Checksum));
			printf("紧急指针:%d\n",ntohs(tcp->UrgPtr));
			char * data;
			data = (char *)((u_char *)tcp+20);
			printf("---------数据部分---------\n");
			printf("数据部分:%s\n",data);

  }
}
 
void ethernet_protocol_packet_callback(u_char *argument,const struct pcap_pkthdr* packet_header,const u_char* packet_content)
{
  u_short ethernet_type;
  struct ether_header *ethernet_protocol;
  u_char *mac_string;
  static int packet_number = 1;
  
  ethernet_protocol=(struct ether_header*)packet_content;//获得数据包内容
  ethernet_type=ntohs(ethernet_protocol->ether_type);//获得以太网类型
  if(ethernet_type==0x0800)//继续分析IP协议
  {

     ip_protool_packet_callback (argument,packet_header,packet_content);
  }
 
  packet_number++;

}
 
int main()
// {
//      pcap_t* pcap_handle; //winpcap句柄
//      char error_content[PCAP_ERRBUF_SIZE]; //存储错误信息
//      bpf_u_int32 net_mask; //掩码地址
//      bpf_u_int32 net_ip;  //网络地址
//      char *net_interface;  //网络接口
//      struct bpf_program bpf_filter;  //BPF过滤规则
//      char bpf_filter_string[]="ip"; //过滤规则字符串,只分析IPv4的数据包
//      net_interface=pcap_lookupdev(error_content); //获得网络接口
//      pcap_lookupnet(net_interface,&net_ip,&net_mask,error_content); //获得网络地址和掩码地址
//      pcap_handle=pcap_open_live(net_interface,BUFSIZ,1,0,error_content); //打开网络接口
//      pcap_compile(pcap_handle,&bpf_filter,bpf_filter_string,0,net_ip); //编译过滤规则
//      pcap_setfilter(pcap_handle,&bpf_filter);//设置过滤规则
//      if (pcap_datalink(pcap_handle)!=DLT_EN10MB) //DLT_EN10MB表示以太网
//          return 0;
//      pcap_loop(pcap_handle,10,ethernet_protocol_packet_callback,NULL); //捕获10个数据包进行分析
//      pcap_close(pcap_handle);
//      return 0;
// }
{
	pcap_if_t * alldevs;
	pcap_if_t * d;
	int inum;
	pcap_t * adhandle;
	char errbuf[PCAP_ERRBUF_SIZE];
	/*取得列表*/
	if(pcap_findalldevs(&alldevs,errbuf) == -1)
	{
		exit(1);
	}
	/*输出列表*/
	for(d=alldevs;d != NULL;d=d->next)
	{
		ifprint(d);
	}
	if(i==0)
	{
 
		printf("\nNo interfaces found!Make sure WinPcap is installed.\n");
		char c = getchar();
		return -1;
	}
	printf("Enter the interface number (1-%d):",i);
	scanf("%d",&inum);
	if(inum <1 || inum >i)
	{
		printf("\nInterface number out of range.\n");
		pcap_freealldevs(alldevs);
		char c = getchar();
		return -1;
	}
	
	//转到选择的设备
	for (d = alldevs,i=0;i <inum-1;d=d->next,i++);
	//打开失败
	if ((adhandle=pcap_open_live(d->name,65536,1,1000,errbuf))==NULL)
	{
		fprintf(stderr,"\nUnable to open the adapter.%s is not supported by WinPcap\n");
		pcap_freealldevs(alldevs);
		char c = getchar();
		return -1;
	}
	printf("\nlistening on %s...\n",d->description);
	//释放列表
	pcap_freealldevs(alldevs);
	//开始捕捉
	//pcap_loop(adhandle,0,ip_protool_packet_callback,NULL);
	pcap_loop(adhandle,0,ethernet_protocol_packet_callback,NULL);
	char c = getchar();
	return 0;
}
void ifprint(pcap_if_t *d)
{
	pcap_addr_t *a;
	printf("%d.%s",++i,d->name);
	if(d->description)
	{
		printf("\tDescription:(%s)\n",d->description);
	}else{
		printf("\t(No description available)\n");
	}
	printf("\tLoopback:%s\n",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no");
	for (a=d->addresses;a != NULL;a=a->next)
	{
		printf("\tAddress Family:#%d\n",a->addr->sa_family);
		switch (a->addr->sa_family)
		{
		case AF_INET:
			printf("\tAddress Family Name:AF_INET\n");
			if(a->addr)
			{
				printf("\tAddress:%s\n",iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr));
			}
			if(a->netmask)
			{
				printf("\tNetmask:%s\n",iptos(((struct sockaddr_in *)a->netmask)->sin_addr.s_addr));
			}
			if(a->broadaddr)
			{
				printf("\tBroadcast Address:%s\n",iptos(((struct sockaddr_in *)a->broadaddr)->sin_addr.s_addr));
			}
			if(a->dstaddr)
			{
				printf("\tDestination Address:%s\n",iptos(((struct sockaddr_in *)a->dstaddr)->sin_addr.s_addr));
			}
			break;
		default:
			printf("\tAddressFamilyName:Unknown\n");
			break;
		}
	}
}
char * iptos(u_long in)
{ 
	static char output[IPTOSBUFFERS][3*4+3+1];
	static short which;
	u_char *p; 
	p = (u_char *)&in;
	which=(which+1==IPTOSBUFFERS?0:which+1); 
	sprintf(output[which],"%d.%d.%d.%d",p[0],p[1],p[2],p[3]);
	return output[which];
}
void packet_handler(u_char *param,const struct pcap_pkthdr *header,const u_char *pcap_data)
{
	struct tm * ltime;
	char timestr[16];
	ltime = localtime(&header->ts.tv_sec);
	strftime(timestr,sizeof(timestr),"%H:%M:%S",ltime);
	printf("%s, %.6d len:%d\n",timestr,header->ts.tv_usec,header->len);
}

程序说明

代码实现需要配置winpcap环境 发送TCP数据包时输入目的IP地址为100.100.100.100 然后输入要发送的数据,即可在接收TCP数据包中收到数据 如果没有收到,把接收TCP数据包关掉重开一下,再试一次就可以了 如果将接受TCP数据包代码中的if判断去掉,即可接受所有TCP数据包

//if(*(unsigned long*)(packet_content+30)==inet_addr("100.100.100.100")){//如果接收端ip地址为100.100.100.100
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值