t-io Java構建p2p網絡

Java 構建p2p網絡

這篇文章是一篇關於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

Java構建項目

在這裏,我將使用maven構建項目,下面是須要使用的工具類:

  • t-io:進行Socket通訊。固然,t-io不是必須的,使用websocket或者netty都是能夠的

項目地址: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

相關文章
相關標籤/搜索