前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用java自造TCP/IP协议栈:使用JPCAP实现数据发包

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

作者头像
望月从良
发布2018-12-20 17:07:25
2.2K0
发布2018-12-20 17:07:25
举报
文章被收录于专栏:Coding迪斯尼Coding迪斯尼

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

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

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

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

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

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

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

代码语言:javascript
复制
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,然后添加如下代码:

代码语言:javascript
复制
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;
            }
        }


    }
}

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

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-11-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Coding迪斯尼 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档