使用java自造TCP/IP协议栈:使用JPCAP实现数据发包

从本节开始,我们打算使用java把tcp/ip网络协议栈重新实现一遍。这是一个不小的野心,自然也是一个不小的工程,好在前面顺利完成了操作系统,编译器两门课程的实现,这给了我极大的信心。整个互联网系统分为三大支柱,分别是操作系统,编译器,和网络协议,我们完成了前面三者,还剩第三者一直孤悬在那,直到今天我终于下定决心,尝试着把tcp/ip协议栈也重新实现一遍。

对于网络协议栈而言,绝大多数人都是”只见过猪跑,但没吃过猪肉“,这绝对是一种巨大的遗憾。网络协议栈构思值巧妙,架构之稳定,非常值得任何期望提升自身技术能力,设计能力,全局思考能力的技术工程师好好把握,把一样东西从无到有,从0到1重新构建出来,绝对是把握其精髓的最佳方式。

我们要开发的协议栈采取四层架构:

屏幕快照 2018-11-27 下午5.38.41.png

协议栈设计的最巧妙之处在于,上层协议只需要关注自己的数据处理,剩下的问题交由下层协议处理,这种方式将一个相当复杂的系统分而治之,一个复杂度极高的系统级怪兽就被庖丁血牛似的给肢解掉了,在后面的编码实现中,我们会感受到此种设计模式的巨大威力。

在上面的架构图中,所有的网络从最顶层开始封包,直到最底部的网卡,数据会转换为电信号被网卡发送给指定服务器或路由器,因此要想再造整个协议栈,我们需要一个功能就是直接操作网卡进行数据包的发送和接收,由此我们使用java开发时,需要有办法直接操作网卡硬件,能帮我们完成该任务的,是常有的java抓包发包组件jpcap。

它是一个jar包,我把它传送到课堂附件,或者大家也可以自行下载。下载到本地后,在eclipse中新建一个项目叫TCPImplementation,当然你也可以任意取自己喜欢的名字,然后在项目目录上右键单击,选择property属性,点击"java build path",然后选择"Libraires",然后点击”add externel jars",然后从下载的jpcap目录下,进入lib目录,然后选择jpcap.jar,接着进入bin目录,选取jpcap.bin,完成后配置如下图:

屏幕快照 2018-11-27 下午5.59.53.png

然后进入jpcap目录下的src/main/c目录,如果像我一样使用macos,那么就打开makefil,找到ifeq else部分代码,然后在该部分的末尾添加如下代码:

ifeq ($(PLATFORM), Darwin)
    JNI_INCLUDE2 = /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/System/Library/Frameworks/JavaVM.framework/versions/A/Headers/ 
    COMPILE_OPTION = -bundle -framework JavaVM
    SUFFIX = .jnilib
endif

添加完后,在控制台执行make命令进行编译,如果使用windows系统,请同学自己百度一下相关配置,编译好后在目录下会有libjpcap.jnilib,将该文件拷贝到目录/Library/Java/Extensions/,如果不是使用macos的同学需要百度一下相应目录或者是jpcap的编译配置方法,最后执行命令sudo chomod 777 /dev/bpf*,如此所有准备工作就完成了。

然后在java工程下新建一个文件ProtocolEntry.java,然后添加如下代码:

import java.io.IOException;

import jpcap.JpcapCaptor;
import jpcap.NetworkInterface;
import jpcap.NetworkInterfaceAddress;
import jpcap.packet.Packet;

public class ProtocolEntry implements PacketReceiver {
	
	public void receivePacket(Packet packet) {
		System.out.println(packet);
		System.out.println("Receive a packet");
	}

	public static void main(String[] args) throws IOException {
		//获取网卡列表
	    NetworkInterface[] devices = JpcapCaptor.getDeviceList();
	    JpcapCaptor captor = null;
	    for (int i = 0; i < devices.length; i++) {
	    	//显示网卡名字
	        System.out.println(i+": "+devices[i].name + "(" + devices[i].description + ")");
	        
	        System.out.println(" datalink: " + devices[i].datalink_name + "(" + devices[i].datalink_description + ")");
	        
	        System.out.println(" Mac Address: ");
	        for (byte b : devices[i].mac_address) {
	            System.out.print(Integer.toHexString(b & 0xff) + ":");
	        }
	        
	        System.out.println();
	        
	        for (NetworkInterfaceAddress a : devices[i].addresses) {
	            System.out.println(" address:" + a.address + " " + a.subnet + " " + a.broadcast);
	        }
	        
	        captor = JpcapCaptor.openDevice(devices[i], 65536, false, 20);
	        if (captor != null) {
	            System.out.println("Open captor on device" + i);
	            break;
	        }
	    }
	    
	   
	}
}

上面代码运行后,结果如下图:

屏幕快照 2018-11-27 下午6.09.42.png

通过jpcap,我们成功访问了网卡硬件,其中"Open captor on device0“,表示我们可以使用名为device0这个网卡来实现数据包的发送和接收,如果你有多块可用网卡,那么这些网卡都可以成功open,后面可以选择其中某一个来进行数据包的发送,至此万里长征,我们成功的走出了第一步!

欢迎关注公众号,让我们一起学习,交流,成长:
文章公众号.jpg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值