全国咨询/投诉热线:400-618-4000

C++培训之网络编程高级应用—libnet 使用指南(一)

更新时间:2016年08月24日10时33分 来源:传智播客C++培训学院 浏览次数:

概述

通过《原始套接字实例:发送 UDP 数据包》的学习,我们组 UDP 数据包时常考虑字节流顺序、校验和计算等问题,有时候会比较繁琐,那么,有没有一种更简单的方法呢?答案是:借助 libnet 函数库。

libnet 是一个小型的接口函数库,主要用 C 语言写成,提供了低层网络数据包的构造、处理和发送功能。

libnet 的开发目的是:建立一个简单统一的网络编程接口以屏蔽不同操作系统底层网络编程的差别,使得程序员将精力集中在解决关键问题上。

libnet 库提供的接口函数包含 15 种数据包生成器和两种数据包发送器(IP 层和数据链路层)。 

提供的接口函数包括:

1)内存管理(分配和释放)函数
2)地址解析函数
3)各种协议类型的数据包构造函数
4)数据包发送函数(IP层和链路层)
5)一些辅助函数,如产生随机数、错误报告、端口列表管理等
详情请看《libnet 函数列表》。
libnet 的安装
流程

利用libnet函数库开发应用程序的基本步骤:

1)数据包内存初始化
2)构造数据包
3)发送数据
4)释放资源

以发送 UDP 数据包为例,流程图如下:

这里需要注意的是组包的顺序,由上层再到底层,这里为 udp -> ip -> mac,不能反过来。


常用函数介绍

以下函数的使用需要包含头文件: libnet.h


libnet_t *libnet_init(int injection_type, char *device, char *err_buf);

功能:

数据包内存初始化及环境建立

参数:

injection_type:构造的类型
LIBNET_LINK,链路层
LIBNET_RAW4,网络接口层(网络层)
LIBNET_LINK_ADV,链路层高级版本
LIBNET_RAW4_ADV,   网络层高级版本
device:网络接口,如 "eth0",或 IP 地址,亦可为 NULL (自动查询搜索)  
err_buf:存放出错的信息 

返回值:

成功:一个 libnet * 类型的指针,后面的操作都得使用这个指针 
失败:NULL

void libnet_destroy(libnet_t *l);

功能:

释放资源

参数:

l:libnet_init() 返回的 libnet * 指针

返回值:


char* libnet_addr2name4(u_int32_t in, u_int8_t use_name);

功能:

将网络字节序转换成点分十进制数串

参数:

in:网络字节序的 ip 地址        
use_name
LIBNET_RESOLVE,  对应主机名
LIBNET_DONT_RESOLVE,对应点分十进制 IPv4 地址

返回值:

成功:点分十进制 ip 地址 
失败:NULL

u_int32_t libnet_name2addr4(libnet_t *l,  char *host_name,  u_int8_t use_name);

功能:

将点分十进制数串转换为网络字节序 ip 地址

参数:

l:libnet_init() 返回的 libnet * 指针
host_name
LIBNET_RESOLVE,  对应主机名
LIBNET_DONT_RESOLVE,对应点分十进制 IPv4 地址

返回值:

成功:网络字节序 ip 地址
失败:-1

u_int32_t libnet_get_ipaddr4(libnet_t *l);

功能:

获取接口设备 ip 地址

参数:

l:libnet_init() 返回的 libnet * 指针

返回值:

成功:网络字节序的 ip 地址
失败:-1

struct libnet_ether_addr* libnet_get_hwaddr(libnet_t *l);

功能:

获取接口设备硬件地址

参数:

l:libnet_init() 返回的 libnet * 指针

返回值:

成功:指向 MAC 地址的指针
失败:NULL

libnet_ptag_t libnet_build_udp(

u_int16_t sp, u_int16_t dp,
u_int16_t len, u_int16_t sum,
u_int8_t *payload, u_int32_t payload_s,
libnet_t *l, libnet_ptag_t ptag);

功能:

构造 udp 数据包

参数:

sp: 源端口号
dp:目的端口号
len:udp 包总长度
sum:校验和,设为 0,libnet 自动填充
payload:负载,为给应用程序发送的文本内容,没有内容时可设置为 NULL
payload_s:负载长度,给应用程序发送文本内容的长度,或为 0
l:libnet_init() 返回的 libnet * 指针
ptag:协议标记,第一次组新的发送包时,这里写 0,同一个应用程序,下一次再组包时,这个位置的值写此函数的返回值。

返回值:


成功:协议标记

失败:-1

libnet_ptag_t libnet_build_tcp(

u_int16_t sp, u_int16_t dp,
u_int32_t seq, u_int32_t ack,
u_int8_t control, u_int16_t win
u_int16_t sum, u_int16_t urg,
u_int16_t len, u_int8_t *payload,
u_int32_t payload_s, libnet_t *l,
libnet_ptag_t ptag );


本文版权归传智播客C++培训学院所有,欢迎转载,转载请注明作者出处。谢谢!
作者:传智播客C/C++培训学院
首发:http://www.itcast.cn/c/