深度剖析WinPcap之(九)――数据包的发送过程(1)

NPF 允许把原始数据包发送到网络上,而且针对不同的应用提供了下列四种发送方式:
n         应用软件每次发送一个数据包一次;
n         应用软件每次发送一个数据包大于一次,次数预先设定;
n         应用软件每次发送一个数据包队列,并根据时间戳发送各数据包;
n         应用软件每次发送一个数据包队列,不根据时间戳,而是尽所能得快速发送各数据包;
数据包被发送到网络时, NPF 并不对数据包作任何协议封装,因此应用程序必须构建每个数据包的不同协议头。一般情况下应用程序不需要生成 FCS ,它通常由网络适配器硬件计算,并在发送到网络前自动添加到每个数据包的尾部。
9-1 函数调用关系图

1.1      wpcap.dll导出的相应函数接口

wpcap.dll 为了完成数据包发送的任务,提供了下列函数:
int pcap_sendpacket(pcap_t *p,u_char *    buf,int size);
函数发送单个原始数据包一次
pcap_send_queue* pcap_sendqueue_alloc(u_int memsize);
函数分配一个发送队列
void pcap_sendqueue_destroy(pcap_send_queue *queue);
函数销毁一个发送队列,释放与队列相关的所有内存资源
int pcap_sendqueue_queue(pcap_send_queue *queue,const struct pcap_pkthdr *pkt_header, const u_char *pkt_data);
函数把一个数据包添加到 queue 参数所指发送队列的尾部
u_int pcap_sendqueue_transmit(pcap_t *p,pcap_send_queue *queue,int sync)
函数发送一个原始数据包队列到网络

1.2      发送单个数据包的示例

我们采用实际代码演示如何通过 pcap_sendpacket 函数发送单个数据包。示例代码如下: [send工程]
#define WIN32
#define HAVE_REMOTE
 
#include <stdio.h>
#include "pcap.h"
#include "Win32-Extensions.h"
 
void genPacket(unsigned char *buf,int len);
 
int main()
{
    pcap_if_t *alldevs;
    pcap_if_t *d;
    int inum;
    int i=0;
    pcap_t *adhandle;
    char errbuf[PCAP_ERRBUF_SIZE];
    int ret=-1;
   
    /* 获取本机网络设备列表 */
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL,
&alldevs, errbuf) == -1)
    {
        fprintf(stderr,
"Error in pcap_findalldevs: %s\n" , errbuf);
        exit(1);
    }
   
    /* 打印网络设备列表 */
    for(d=alldevs; d; d=d->next)
    {
        printf("%d. %s", ++i, d->name);
        if (d->description)
            printf(" (%s)\n", d->description);
        else
            printf(" (No description available)\n");
    }
   
    if(i==0)
    {
        printf("\nNo interfaces found! Make sure
WinPcap is installed.\n" );
        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);
        return -1;
    }
   
    /* 跳转到选中的适配器 */
    for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);
   
    /* 打开设备 */
if ( (adhandle= pcap_open(d->name, 65536,
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;
    }
 
    /* 在选中的设备接口上监听数据 */
    printf("\nlistening on %s...\n", d->description);
   
 
   
    /* 开始数据包发送 */    
    int MaxPacketLen=100;
    unsigned char *pBuf= (unsigned char *)malloc(MaxPacketLen);
    memset(pBuf,0x0,MaxPacketLen);
// 获得生成的数据包,长度为 MaxPacketLen
    genPacket(pBuf,MaxPacketLen);
 
    if ( (ret=pcap_sendpacket(adhandle,pBuf,MaxPacketLen))
==-1)
    {
       printf(" 发送失败 \n" );
       pcap_close(adhandle);
        pcap_freealldevs(alldevs);
        return -1;
    }
 
 
     /* 释放资源 */
     free(pBuf);
     pcap_close(adhandle);
     pcap_freealldevs(alldevs);
   
    return 0;
}
其中函数genPacket负责生成数据包,参数buf用来保存所生成数据包的内容,len为要求深成数据包的长度。该函数所生成的数据包没有任何实际意义,仅仅为了演示。函数源代码如下:
void genPacket(unsigned char *buf,int len)
{
       int i=0;
       // 设置目标 MAC 地址为 :01:01:01:01:01
       for (i=0;i<6;i++)
       {
           buf[i]=0x01;
       }
       // 设置源 MAC 地址为 :02:02:02:02:02
       for (i=6;i<12;i++)
       {
           buf[i]=0x02;
       }
       // 设置协议标识为 xc0xd ,无任何实际意义
       buf[12]=0xc;
       buf[13]=0xd; 
       // 填充数据包的内容  
       for(i=14;i<len;i++)
       {         
           buf[i]=i-14;
       }
}
Wireshark 接收示例程序所发送的数据包如图 9-2 所示。
9-2 Wireshark所接收的数据包

你可能感兴趣的:(职场,休闲,winpcap)