Jnetpcap

实验目的

  1. 捕获IP数据包并解析,显示并写入日志文件。我是自己边学边写的奥,在做TCP/IP的课程设计,一直到验收完我才会发布。
  2. 一些基础知识大家自己去了解吧包括网络编程,以太网对数据帧的封装,IP数据报格式。
  3. 我的实验环境是:Windows,Eclipse,Java,Jnetpcap。

基础知识

  1. 以太网帧结构:数据帧(Frame)是数据链路层的数据单元,以太网的帧结构注意帧头的信息(MAC地址,协议类型等)。
  2. 数据包(Packet):TCP/IP协议通信传输中的数据单位,封装在Frame中。

实验步骤

一、查找并获取网络接口名称,以便我们可以告诉jNetPcap打开一个或多个以进行读取。因此,首先我们查询系统上的接口列表:

public static int findAllDevs(java.util.List < PcapIf > alldevs,
                              java.lang.StringBuilder errbuf)

参数:
alldevs-列表中填充了PcapIf接口对象;列表一定不能一成不变
errbuf -错误缓冲区,包含错误消息,失败时为字符串
返回值:
失败时返回-1,在这种情况下,errbuf会填入适当的错误消息;成功返回0

  • alldevs列表中的每个元素的类型为pcap_if_t,其结构体和pcap_if相同,用来描述网络设备结构,结构成员如下:
struct pcap_if {
struct pcap_if *next; //指向列表中下一个元素的指针
char *name;           //该字符串为设备传递给pcap_open_live()的名称
char *description;    //如果不为NULL,则为指向字符串的指针,该字符串给出了设备可读的描述
struct pcap_addr *addresses; //指向接口地址列表中第一个元素的指针
bpf_u_int32 flags;    //如果接口是回送接口,则设置PCAP_IF_LOOPBACK
};
  • 上面结构体的 pcap_addr 的数据结构,同样有五个属性:ip地址、子网掩码、广播地址、目标地址
struct pcap_addr {
struct pcap_addr *next; //指向列表中下一个元素的指针;列表的最后一个元素为NULL
struct sockaddr *addr; //指向包含地址的struct sockaddr的指针
struct sockaddr *netmask; //如果不为NULL,则指向结构sockaddr的指针,该结构包含与addr指向的地址相对应的网络掩码
struct sockaddr *broadaddr; //指向结构sockaddr的指针,该结构包含与addr指向的地址相对应的广播地址;如果接口不支持广播,则可以为null
struct sockaddr *dstaddr; //指向结构sockaddr的指针,其中包含与addr指向的地址相对应的目标地址;如果接口不是点对点接口,则可以为null
};
  • 还有关于sockaddr,sockaddr_in,in_addr的结构体,可以理解为就是网络编程时表示IP地址,具体的IP地址有多种表示方法:网络字节序,点分十进制等等,也有具体的函数实现各种表示方式之间的转换。

二、打开与指定的网络接口设备关联的实时捕获。

public static Pcap openLive(java.lang.String device,
                            int snaplen,
                            int promisc,
                            int timeout,
                            java.lang.StringBuilder errbuf)

参数:
device:指定要打开的网络设备的字符串
snaplen:指定要捕获的最大字节数
promisc:指定是否将接口置于混杂模式
timeout:以毫秒为单位指定读取超时
errbuf:返回错误或警告文本
返回值:
原始结构pcap_t原始libpcap调用返回的C结构数据打开

  • snaplen指定的是可以捕获的最大的字节数,如果 snaplen的值比我们捕获的包的大小要小, 那么只有snaplen大小的数据会被捕获并以packet data的形式提供。

  • IP数据报的最大长度是65535,而以太网的MTU为1500 字节,为了使IP数据包能够通过,必须要进行分片。下图是使用ping命令发送5000字节ICMP请求时,使用wireshark抓的包。(IP数据包中和分片有关的字段:标识、标志、分片偏移)
    IP报文分片

  • promisc -1表示处于混杂模式,0表示非混杂。Pcap.MODE_PROMISCUOUS,该模式用于网络信息监视捕捉,监视所有经过网卡的数据包,包括不是发给本机的数据包。

三、编译过滤器并将其应用于网络接口

通常我们只对特定网络通信感兴趣。可以通过compile()和setfilter()来设置数据流过滤规则。

  • 编译一个数据包过滤器,将高级过滤表达式转换为可由内核级过滤引擎解释的程序。
public int compile(PcapBpfProgram program,
                   java.lang.String str,
                   int optimize,
                   int netmask)

参数:
program :PcapBpfProgram过滤器对象
str :包含要编译的文本表达式的字符串
optimize :1表示进行优化,任何其他值表示没有
netmask :确定广播地址所需的网络掩码
返回值:
1表示错误,在这种情况下getErr() 可用于显示错误文本。

  • PcapBpfProgram对象遵循BPF过滤规则,使用str过滤表达式来指定过滤规则。
PcapBpfProgram filter = new PcapBpfProgram();
		String expression = "tcp";
		 int res = pcap.compile(filter, expression, 1, 0);
		 pcap.setFilter(filter);
		 if (res != 0) {
			 System.out.println("Filter error:" + pcap.getErr());
		 }
  • 指定过滤程序
public int setFilter(PcapBpfProgram program)

四、捕获数据包

public <T> int loop(int cnt,
                   PcapPacketHandler<T> handler,
                   T user)

参数:
cnt -要处理的数据包数量
handler -用户提供的数据包处理程序
user -自定义不透明用户对象
返回值:
成功时为0,错误时为-1,如果使用了breakloop,则为-2中断验证

pcap_loop()一直读取数据包,直到处理cnt数据包或发生错误为止。

五、关闭pcap

必须调用close()释放所有Libpcap资源。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值