一.JPCAP簡介
眾所周知,JAVA語言雖然在TCP/UDP傳輸方面給予了良好的定義,但對于網(wǎng)絡(luò)層以下的控制,卻是無能為力的。JPCAP擴(kuò)展包彌補(bǔ)了這一點(diǎn)。
JPCAP實際上并非一個真正去實現(xiàn)對數(shù)據(jù)鏈路層的控制,而是一個中間件,JPCAP調(diào)用wincap/libpcap,而給JAVA語言提供一個公共的接口,從而實現(xiàn)了平臺無關(guān)性。在官方網(wǎng)站上聲明,JPCAP支持FreeBSD 3.x, Linux RedHat 6.1, Fedora Core 4, Solaris, and Microsoft Windows 2000/XP等系統(tǒng)。
二.JPCAP機(jī)制
JPCAP的整個結(jié)構(gòu)大體上跟wincap/libpcap是很相像的,例如NetworkInterface類對應(yīng)wincap的typedef struct _ADAPTERADAPTER,getDeviceList()對應(yīng)pcap_findalldevs()等等。 JPCAP有16個類,下面就其中最重要的4個類做說明。
1.NetworkInterface
該類的每一個實例代表一個網(wǎng)絡(luò)設(shè)備,一般就是網(wǎng)卡。這個類只有一些數(shù)據(jù)成員,除了繼承自java.lang.Object的基本方法以外,沒有定義其它方法。
數(shù)據(jù)成員
NetworkInterfaceAddress[]
java.lang.String
datalink_description.
數(shù)據(jù)鏈路層的描述。描述所在的局域網(wǎng)是什么網(wǎng)。例如,以太網(wǎng)(Ethernet)、無線LAN網(wǎng)(wireless LAN)、令牌環(huán)網(wǎng)(token ring)等等。
java.lang.String
datalink_name
該網(wǎng)絡(luò)設(shè)備所對應(yīng)數(shù)據(jù)鏈路層的名稱。具體來說,例如Ethernet10M、100M、1000M等等。
java.lang.String
description
網(wǎng)卡是XXXX牌子XXXX型號之類的描述。例如我的網(wǎng)卡描述:Realtek RTL8169/8110 Family Gigabit Ethernet NIC
boolean
Loopback
標(biāo)志這個設(shè)備是否loopback設(shè)備。
byte[]
mac_address
網(wǎng)卡的MAC地址,6個字節(jié)。
java.lang.String
Name
這個設(shè)備的名稱。例如我的網(wǎng)卡名稱:\Device\NPF_{3CE5FDA5-E15D-4F87-B217-255BCB351CD5}
2.JpcapCaptor
該類提供了一系列靜態(tài)方法實現(xiàn)一些基本的功能。該類一個實例代表建立了一個與指定設(shè)備的鏈接,可以通過該類的實例來控制設(shè)備,例如設(shè)定網(wǎng)卡模式、設(shè)定過濾關(guān)鍵字等等。
數(shù)據(jù)成員
int
dropped_packets
拋棄的包的數(shù)目。
protected int
ID
這個數(shù)據(jù)成員在官方文檔中并沒有做任何說明,查看JPCAP源代碼可以發(fā)現(xiàn)這個ID實際上在其JNI的C代碼部分傳進(jìn)來的,這類本身并沒有做出定義,所以是供其內(nèi)部使用的。實際上在對JpcapCator實例的使用中也沒有辦法調(diào)用此數(shù)據(jù)成員。
protected staticboolean[]
instanciatedFlag
同樣在官方文檔中沒有做任何說明,估計其為供內(nèi)部使用。
protected staticint
MAX_NUMBER_OF_INSTANCE
同樣在官方文檔中沒有做任何說明,估計其為供內(nèi)部使用。
int
received_packets
收到的包的數(shù)目
方法成員
staticNetworkInterface[]
getDeviceList()
返回一個網(wǎng)絡(luò)設(shè)備列表。
staticJpcapCaptor
openDevice(NetworkInterface interface, intsnaplen, booleanpromisc, intto_ms)
創(chuàng)建一個與指定設(shè)備的連接并返回該連接。注意,以上兩個方法都是靜態(tài)方法。
Interface:要打開連接的設(shè)備的實例;
Snaplen:這個是比較容易搞混的一個參數(shù)。其實這個參數(shù)不是限制只能捕捉多少數(shù)據(jù)包,而是限制每一次收到一個數(shù)據(jù)包,只提取該數(shù)據(jù)包中前多少字節(jié);
Promisc:設(shè)置是否混雜模式。處于混雜模式將接收所有數(shù)據(jù)包,若之后又調(diào)用了濾函數(shù)setFilter()將不起任何作用;
To_ms:這個參數(shù)主要用于processPacket()方法,指定超時的時間;
void
Close()
關(guān)閉調(diào)用該方法的設(shè)備的連接,相對于openDivece()打開連接。
JpcapSender
getJpcapSenderInstance()
該返回一個JpcapSender實例,JpcapSender類是專門用于控制設(shè)備的發(fā)送數(shù)據(jù)包的功能的類。
Packet
getPacket()
捕捉并返回一個數(shù)據(jù)包。這是JpcapCaptor實例中四種捕捉包的方法之一。
int
loopPacket(intcount, PacketReceiver handler)
捕捉指定數(shù)目的數(shù)據(jù)包,并交由實現(xiàn)了PacketReceiver接口的類的實例處理,并返回捕捉到的數(shù)據(jù)包數(shù)目。如果count參數(shù)設(shè)為-1,那么無限循環(huán)地捕捉數(shù)據(jù)。
這個方法不受超時的影響。還記得openDivice()中的to_ms參數(shù)么?那個參數(shù)對這個方法沒有影響,如果沒有捕捉到指定數(shù)目數(shù)據(jù)包,那么這個方法將一直阻塞等待。
PacketReceiver中只有一個抽象方法void receive(Packet p)。
int
processPacket(intcount, PacketReceiver handler)
跟loopPacket()功能一樣,的區(qū)別是這個方法受超時的影響,超過指定時間自動返回捕捉到數(shù)據(jù)包的數(shù)目。
int
dispatchPacket(intcount, PacketReceiverhandler)
跟processPacket()功能一樣,區(qū)別是這個方法可以處于“non-blocking”模式工作,在這種模式下dispatchPacket()可能立即返回,即使沒有捕捉到任何數(shù)據(jù)包。
void
setFilter(java.lang.Stringcondition, booleanoptimize)
.condition:設(shè)定要提取的包的關(guān)鍵字。
Optimize:這個參數(shù)在說明文檔以及源代碼中都沒有說明,只是說這個參數(shù)如果為真,那么過濾器將處于優(yōu)化模式。
void
setNonBlockingMode(booleannonblocking)
如果值為“true”,那么設(shè)定為“non-blocking”模式。
void
breakLoop()
當(dāng)調(diào)用processPacket()和loopPacket()后,再調(diào)用這個方法可以強(qiáng)制讓processPacket()和loopPacket()停止。
3.JpcapSender
該類專門用于控制數(shù)據(jù)包的發(fā)送。
方法成員
void
close()
強(qiáng)制關(guān)閉這個連接。
staticJpcapSender
openRawSocket()
這個方法返回的JpcapSender實例發(fā)送數(shù)據(jù)包時將自動填寫數(shù)據(jù)鏈路層頭部分。
void
sendPacket(Packet packet)
JpcapSender最重要的功能,發(fā)送數(shù)據(jù)包。需要注意的是,如果調(diào)用這個方法的實例是由JpcapCaptor的getJpcapSenderInstance()得到的話,需要自己設(shè)定數(shù)據(jù)鏈路層的頭,而如果是由上面的openRawSocket()得到的話,那么無需也不能設(shè)置,數(shù)據(jù)鏈路層的頭部將由系統(tǒng)自動生成。
4.Packet
這個是所有其它數(shù)據(jù)包類的父類。Jpcap所支持的數(shù)據(jù)包有:
ARPPacket、DatalinkPacket、EthernetPacket、ICMPPacket、IPPacket、TCPPacket、UDPPacket
眾所周知,JAVA語言雖然在TCP/UDP傳輸方面給予了良好的定義,但對于網(wǎng)絡(luò)層以下的控制,卻是無能為力的。JPCAP擴(kuò)展包彌補(bǔ)了這一點(diǎn)。
JPCAP實際上并非一個真正去實現(xiàn)對數(shù)據(jù)鏈路層的控制,而是一個中間件,JPCAP調(diào)用wincap/libpcap,而給JAVA語言提供一個公共的接口,從而實現(xiàn)了平臺無關(guān)性。在官方網(wǎng)站上聲明,JPCAP支持FreeBSD 3.x, Linux RedHat 6.1, Fedora Core 4, Solaris, and Microsoft Windows 2000/XP等系統(tǒng)。
二.JPCAP機(jī)制
JPCAP的整個結(jié)構(gòu)大體上跟wincap/libpcap是很相像的,例如NetworkInterface類對應(yīng)wincap的typedef struct _ADAPTERADAPTER,getDeviceList()對應(yīng)pcap_findalldevs()等等。 JPCAP有16個類,下面就其中最重要的4個類做說明。
1.NetworkInterface
該類的每一個實例代表一個網(wǎng)絡(luò)設(shè)備,一般就是網(wǎng)卡。這個類只有一些數(shù)據(jù)成員,除了繼承自java.lang.Object的基本方法以外,沒有定義其它方法。
數(shù)據(jù)成員
NetworkInterfaceAddress[]
java.lang.String
datalink_description.
數(shù)據(jù)鏈路層的描述。描述所在的局域網(wǎng)是什么網(wǎng)。例如,以太網(wǎng)(Ethernet)、無線LAN網(wǎng)(wireless LAN)、令牌環(huán)網(wǎng)(token ring)等等。
java.lang.String
datalink_name
該網(wǎng)絡(luò)設(shè)備所對應(yīng)數(shù)據(jù)鏈路層的名稱。具體來說,例如Ethernet10M、100M、1000M等等。
java.lang.String
description
網(wǎng)卡是XXXX牌子XXXX型號之類的描述。例如我的網(wǎng)卡描述:Realtek RTL8169/8110 Family Gigabit Ethernet NIC
boolean
Loopback
標(biāo)志這個設(shè)備是否loopback設(shè)備。
byte[]
mac_address
網(wǎng)卡的MAC地址,6個字節(jié)。
java.lang.String
Name
這個設(shè)備的名稱。例如我的網(wǎng)卡名稱:\Device\NPF_{3CE5FDA5-E15D-4F87-B217-255BCB351CD5}
2.JpcapCaptor
該類提供了一系列靜態(tài)方法實現(xiàn)一些基本的功能。該類一個實例代表建立了一個與指定設(shè)備的鏈接,可以通過該類的實例來控制設(shè)備,例如設(shè)定網(wǎng)卡模式、設(shè)定過濾關(guān)鍵字等等。
數(shù)據(jù)成員
int
dropped_packets
拋棄的包的數(shù)目。
protected int
ID
這個數(shù)據(jù)成員在官方文檔中并沒有做任何說明,查看JPCAP源代碼可以發(fā)現(xiàn)這個ID實際上在其JNI的C代碼部分傳進(jìn)來的,這類本身并沒有做出定義,所以是供其內(nèi)部使用的。實際上在對JpcapCator實例的使用中也沒有辦法調(diào)用此數(shù)據(jù)成員。
protected staticboolean[]
instanciatedFlag
同樣在官方文檔中沒有做任何說明,估計其為供內(nèi)部使用。
protected staticint
MAX_NUMBER_OF_INSTANCE
同樣在官方文檔中沒有做任何說明,估計其為供內(nèi)部使用。
int
received_packets
收到的包的數(shù)目
方法成員
staticNetworkInterface[]
getDeviceList()
返回一個網(wǎng)絡(luò)設(shè)備列表。
staticJpcapCaptor
openDevice(NetworkInterface interface, intsnaplen, booleanpromisc, intto_ms)
創(chuàng)建一個與指定設(shè)備的連接并返回該連接。注意,以上兩個方法都是靜態(tài)方法。
Interface:要打開連接的設(shè)備的實例;
Snaplen:這個是比較容易搞混的一個參數(shù)。其實這個參數(shù)不是限制只能捕捉多少數(shù)據(jù)包,而是限制每一次收到一個數(shù)據(jù)包,只提取該數(shù)據(jù)包中前多少字節(jié);
Promisc:設(shè)置是否混雜模式。處于混雜模式將接收所有數(shù)據(jù)包,若之后又調(diào)用了濾函數(shù)setFilter()將不起任何作用;
To_ms:這個參數(shù)主要用于processPacket()方法,指定超時的時間;
void
Close()
關(guān)閉調(diào)用該方法的設(shè)備的連接,相對于openDivece()打開連接。
JpcapSender
getJpcapSenderInstance()
該返回一個JpcapSender實例,JpcapSender類是專門用于控制設(shè)備的發(fā)送數(shù)據(jù)包的功能的類。
Packet
getPacket()
捕捉并返回一個數(shù)據(jù)包。這是JpcapCaptor實例中四種捕捉包的方法之一。
int
loopPacket(intcount, PacketReceiver handler)
捕捉指定數(shù)目的數(shù)據(jù)包,并交由實現(xiàn)了PacketReceiver接口的類的實例處理,并返回捕捉到的數(shù)據(jù)包數(shù)目。如果count參數(shù)設(shè)為-1,那么無限循環(huán)地捕捉數(shù)據(jù)。
這個方法不受超時的影響。還記得openDivice()中的to_ms參數(shù)么?那個參數(shù)對這個方法沒有影響,如果沒有捕捉到指定數(shù)目數(shù)據(jù)包,那么這個方法將一直阻塞等待。
PacketReceiver中只有一個抽象方法void receive(Packet p)。
int
processPacket(intcount, PacketReceiver handler)
跟loopPacket()功能一樣,的區(qū)別是這個方法受超時的影響,超過指定時間自動返回捕捉到數(shù)據(jù)包的數(shù)目。
int
dispatchPacket(intcount, PacketReceiverhandler)
跟processPacket()功能一樣,區(qū)別是這個方法可以處于“non-blocking”模式工作,在這種模式下dispatchPacket()可能立即返回,即使沒有捕捉到任何數(shù)據(jù)包。
void
setFilter(java.lang.Stringcondition, booleanoptimize)
.condition:設(shè)定要提取的包的關(guān)鍵字。
Optimize:這個參數(shù)在說明文檔以及源代碼中都沒有說明,只是說這個參數(shù)如果為真,那么過濾器將處于優(yōu)化模式。
void
setNonBlockingMode(booleannonblocking)
如果值為“true”,那么設(shè)定為“non-blocking”模式。
void
breakLoop()
當(dāng)調(diào)用processPacket()和loopPacket()后,再調(diào)用這個方法可以強(qiáng)制讓processPacket()和loopPacket()停止。
3.JpcapSender
該類專門用于控制數(shù)據(jù)包的發(fā)送。
方法成員
void
close()
強(qiáng)制關(guān)閉這個連接。
staticJpcapSender
openRawSocket()
這個方法返回的JpcapSender實例發(fā)送數(shù)據(jù)包時將自動填寫數(shù)據(jù)鏈路層頭部分。
void
sendPacket(Packet packet)
JpcapSender最重要的功能,發(fā)送數(shù)據(jù)包。需要注意的是,如果調(diào)用這個方法的實例是由JpcapCaptor的getJpcapSenderInstance()得到的話,需要自己設(shè)定數(shù)據(jù)鏈路層的頭,而如果是由上面的openRawSocket()得到的話,那么無需也不能設(shè)置,數(shù)據(jù)鏈路層的頭部將由系統(tǒng)自動生成。
4.Packet
這個是所有其它數(shù)據(jù)包類的父類。Jpcap所支持的數(shù)據(jù)包有:
ARPPacket、DatalinkPacket、EthernetPacket、ICMPPacket、IPPacket、TCPPacket、UDPPacket