这篇文章是一篇关于pbft算法实现的一篇补充文章,可是在这里不会涉及pbft的算法方面,因此能够当作一篇单独的文章食用。若是想查看关于区块链或者PBFT算法的文章,能够参考一下个人文章。html
这篇文章是构建一个p2p网络,须要拥有独立的ip地址(固然若是是在局域网内使用就无所谓了),不会涉及到内网穿透的一些实现方法,也就是说若是你是把本身电脑构建了一个p2p结点,则其余人的电脑是没法连接你电脑的结点的。java
p2p网络中,一个结点既是客户端也是服务端,能够实现任意时刻的双向的通讯。所以在每一个结点中,会维护一张客户端的表和一张服务端的表。咱们能够从代码的方面来理解一下这个东西,以下图所示:git
两个被方框圈住的表则是须要维护的表,若是在代码中的话,咱们就可使用List去保存这张表github
客户端的表咱们能够用来发送消息,而服务端的表咱们能够用来控制群发。web
这里咱们能够解释和理解一下何为p2p。举例:算法
结点1想与结点2进行通讯时:A1跑出来讲,我有到结点2的通道,而后向结点2发出request
,结点2的服务端接收到结点1(A1)发出来的消息的时,进行response。websocket
这个时候,可能就会有人问:为何不是结点1的服务端向结点2发出request呢,而后结点2再向服务端返回response?yes,这个是能够的,而且可以成功。那是否是意味着客户端的表实际上能够不要?固然不是!!!
首先咱们从哲学的角度理解这个东西,request理所固然应该是client发出来的,response也应当是response发出来的。固然,这个彻底是扯蛋。在两个结点中,一个当作server一个当作client,这样确实不会出现问题,当时若是是3个节点呢?这样作能不能实现两两单独
发送呢?很抱歉,不能。(注意,在这里是两个结点直接进行request和response,而不借助其余结点)。网络
下面这种模式是一个结点只为Server,另外的几个也只为Client。在这种模式中,C1和其余的结点没法独自进行两两通讯,必须借助Server来进行通讯。
框架
OK,说了这么多,那么如今让咱们来进行构建P2P网络socket
在这里,我将使用maven构建项目,下面是须要使用的工具类:
项目地址:github
代码其实没什么好讲的,主要是不熟悉tio的使用,这里,emm,吐槽一下tio,妈耶,文档也太贵了吧(╮(╯▽╰)╭,学生优惠没有了,哭唧唧)。
代码其实很简单,就是开上几个server,而后client链接Server就好了。
主要代码以下所示(实际上使用什么框架都行,本身喜欢就行,把思路弄好就能够了):
public static void main(String[] args) { Scanner in = new Scanner(System.in); String ip = "127.0.0.1"; // 服务端开始 System.out.println("请输入服务端初始化端口:"); int port = in.nextInt(); // 处理消息handler ServerAioHandler handler = new P2PServerAioHandler(); // 监听 ServerAioListener listener = new ServerListener(); // 配置 ServerTioConfig config = new ServerTioConfig("服务端", handler, listener); // 设置timeout config.setHeartbeatTimeout(Const.TIMEOUT *2); TioServer tioServer = new TioServer(config); try { // 启动 tioServer.start(ip, port); } catch (IOException e) { System.out.println("启动错误:" + e.getMessage()); } // client开始 ClientChannelContext[] contexts = new ClientChannelContext[3]; for (int i = 0; i < 3; i++) { // client的handler ClientAioHandler clientAioHandler = new P2pClientAioHandler(); // client 的配置 ClientTioConfig clientTioConfig = new ClientTioConfig(clientAioHandler, new P2PClientLinstener(),new ReconnConf(Const.TIMEOUT)); clientTioConfig.setHeartbeatTimeout(Const.TIMEOUT); ClientChannelContext context; try { TioClient client = new TioClient(clientTioConfig); System.out.println("输入端口:"); int serverPort = in.nextInt(); context = client.connect(new Node(ip, serverPort), Const.TIMEOUT); contexts[i] = context; } catch (Exception e) { System.out.println("客户端启动错误:" + e.getMessage()); } } while (true) { System.out.println("请输入发送的服务端的index"); int index = in.nextInt(); System.out.println("请输入发送的内容"); String body = in.next(); try { MsgPacket msgPacket = new MsgPacket(); msgPacket.setBody("测试数据".getBytes(MsgPacket.CHARSET)); Tio.send(contexts[index], msgPacket); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } }
思路:
思路仍是蛮简单的,先进行server建立,并对他进行配置(配置它的消息处理方式和一些超时属性等等),在tio中,server会在后台(也就是P2PServerAioHandler这个类)接受并处理消息。而后是配置client,一样配置一些Handler和timeout等等。在这里我使用了ClientChannelContext[] contexts = new ClientChannelContext[3]
来保存client。ClientChannelContext能够理解为client到server的一根管道,经过他咱们能够来控制消息的发送。
项目地址:GitHub
原文出处:https://www.cnblogs.com/xiaohuiduan/p/12302024.html