JAVA抓取网卡IP数据包

我们经常使用Httpwatch查看HTTP的传输数据。那java能不能做到呢?  下面我们就讲一下如何通过java在windows上获取网卡的数据包,这里我们使用了开源的WinPcap,还有jNetPcap,jNetPcap是对接了WinPcap来截获网卡数据包。

如何截获网卡分3步:

1. 在自己的机器上安装WinPcap。   http://www.winpcap.org/install/default.htm

2. 下载jNetPcap,     http://jnetpcap.com/download.  下载下来之后解压,里面2个重要文件jnetpcap.jar,jnetpcap.dll

3  在eclipse里新建工程,把jnetpcap.jar加入library.  然后参考如下代码实现网卡截包:

 

import java.util.ArrayList;
import java.util.List;

import org.jnetpcap.Pcap;
import org.jnetpcap.PcapIf;
import org.jnetpcap.packet.JPacket;
import org.jnetpcap.packet.JPacketHandler;
import org.jnetpcap.protocol.tcpip.Http;
import org.jnetpcap.protocol.tcpip.Tcp;

/**
 * Capture the netword card packages
 * 
 */
public class App {
	public static void main(String[] args) throws InterruptedException {
		List alldevs = new ArrayList(); // Will be filled with
														// NICs
		StringBuilder errbuf = new StringBuilder();
		int r = Pcap.findAllDevs(alldevs, errbuf);
		if (r == Pcap.NOT_OK || alldevs.isEmpty()) {
			System.err.printf("Can't read list of devices, error is %s",
					errbuf.toString());
			return;
		}
		for (PcapIf pif : alldevs) {
			System.out.println(pif.getName());
		}

		PcapIf pif = alldevs.get(0);//select the device which you want to monitor 

		/***************************************
		 * open the device
		 ***************************************/
		int snaplen = 64 * 1024; // Capture all packets, no trucation
		int flags = Pcap.MODE_PROMISCUOUS; // capture all packets
		int timeout = 10 * 1000; // 10 seconds in millis
		Pcap pcap = Pcap.openLive(pif.getName(), snaplen, flags, timeout,
				errbuf);

		if (pcap == null) {
			System.err.printf("Error while opening device for capture: "
					+ errbuf.toString());
			return;
		}
		
		/* 
         * We have an opened the capture file now time to read packets. We use a 
         * Pcap.loop function to retrieve 10 packets from the file. We supply an 
         * annonymous handler which will receive packets as they are read from the 
         * offline file by libpcap. We parameterize it with a StringBuilder class. 
         * This allows us to pass in any type of object we need inside the our 
         * dispatch handler. For this example we are passing in the errorbuf object 
         * so we can pass back a string, if we need to. Of course in our example 
         * this is not strictly needed since our anonymous class can access errbuf 
         * object directly from the enclosing main method as that local variable is 
         * marked final allowing anonymous classes access to it. 
         */  
        pcap.loop(Pcap.LOOP_INFINITE, new JPacketHandler() {  
  
            /** 
             * We purposely define and allocate our working tcp header (accessor) 
             * outside the dispatch function and thus the libpcap loop, as this type 
             * of object is reusable and it would be a very big waist of time and 
             * resources to allocate it per every dispatch of a packet. We mark it 
             * final since we do not plan on allocating any other instances of Tcp. 
             */  
            final Tcp tcp = new Tcp();  
          
  
            /* 
             * Same thing for our http header 
             */  
            final Http http = new Http();  
            
           
  
            /** 
             * Our custom handler that will receive all the packets libpcap will 
             * dispatch to us. This handler is inside a libpcap loop and will receive 
             * exactly 10 packets as we specified on the Pcap.loop(10, ...) line 
             * above. 
             *  
             * @param packet 
             *          a packet from our capture file 
             * @param errbuf 
             *          our custom user parameter which we chose to be a StringBuilder 
             *          object, but could have chosen anything else we wanted passed 
             *          into our handler by libpcap 
             */  
            public void nextPacket(JPacket packet, StringBuilder errbuf) {  
  
                /* 
                 * Here we receive 1 packet at a time from the capture file. We are 
                 * going to check if we have a tcp packet and do something with tcp 
                 * header. We are actually going to do this twice to show 2 different 
                 * ways how we can check if a particular header exists in the packet and 
                 * then get that header (peer header definition instance with memory in 
                 * the packet) in 2 separate steps. 
                 */  
                if (packet.hasHeader(Tcp.ID)) {  
  
                    /* 
                     * Now get our tcp header definition (accessor) peered with actual 
                     * memory that holds the tcp header within the packet. 
                     */  
                    packet.getHeader(tcp); 
                    
                    System.out.printf("tcp.dst_port=%d%n", tcp.destination());  
                    System.out.printf("tcp.src_port=%d%n", tcp.source());  
                    System.out.printf("tcp.ack=%x%n", tcp.ack());  
  
                }  
  
                /* 
                 * An easier way of checking if header exists and peering with memory 
                 * can be done using a conveniece method JPacket.hasHeader(? extends 
                 * JHeader). This method performs both operations at once returning a 
                 * boolean true or false. True means that header exists in the packet 
                 * and our tcp header difinition object is peered or false if the header 
                 * doesn't exist and no peering was performed. 
                 */  
                if (packet.hasHeader(tcp)) {  
                    //System.out.printf("tcp header::%s%n", tcp.toString());  
                }  
  
                /* 
                 * A typical and common approach to getting headers from a packet is to 
                 * chain them as a condition for the if statement. If we need to work 
                 * with both tcp and http headers, for example, we place both of them on 
                 * the command line. 
                 */  
                if (packet.hasHeader(tcp) && packet.hasHeader(http)) {  
                    /* 
                     * Now we are guarranteed to have both tcp and http header peered. If 
                     * the packet only contained tcp segment even though tcp may have http 
                     * port number, it still won't show up here since headers appear right 
                     * at the beginning of http session. 
                     */  
  
                	
                    System.out.printf("http header::%s%n", http);  
  
                    /* 
                     * jNetPcap keeps track of frame numbers for us. The number is simply 
                     * incremented with every packet scanned. 
                     */  
  
                }  
  
                //System.out.printf("frame #%d%n", packet.getFrameNumber());  
            }  
  
        }, errbuf);  

		/*
		 * Last thing to do is close the pcap handle
		 */
		pcap.close();
	}
}

 注意:

在运行以上代码之前还需要加上jvm参数,为了让jnetpcap找到jnetpcap.dll,我们在vm parameters加入以下参数:

-Djava.library.path=E:\jnetpcap

这里的E:\jnetpcap 就是jnetpcap.dll放置的目录。

 
JAVA抓取网卡IP数据包_第1张图片
 

 

 

 

 

你可能感兴趣的:(winpcap,jnetpcap,java抓包)