国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java中Nio編程實現網絡編程的多客戶端與服務器連接完整步驟

不知名網友 / 2565人閱讀

摘要:編程核心是通道和選擇器,選擇器通過不斷輪詢,執行對應的函數。所以我們需要捕獲這個異常,并且開始不斷重連。如果客戶端關閉那么服務器也要主動關閉他數據庫代碼及實體類如果還想實現數據庫方面代碼,私我

前言:

物聯網答辯終于結束了 記一下自己網絡編程的代碼 重連代碼寫了好久 try catch原來可以這么用!

學習地址:https://www.bilibili.com/video/BV1gz4y1C7RK

項目結構:

1、服務器代碼:

package Server;import Entiles.User;import Utils.JdbcUtil;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.*;import java.nio.charset.Charset;import java.text.SimpleDateFormat;import java.util.Iterator;import java.util.Scanner;import java.util.Set;public class ChatServer {    public void StratServer(int port) throws IOException {        //soket通道 客戶通道        //創建服務端通道        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();        //非堵塞模式        serverSocketChannel.configureBlocking(false);        //創建buffer        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);        //綁定端口        serverSocketChannel.bind(new InetSocketAddress(port));        //創建selector 選擇器        Selector selector = Selector.open();        //注冊通道        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);        //輪播查詢        System.out.println("智能水表服務端(端口:"+port+")已經啟動");//        如果有就緒狀態的通道 則select方法返回1        while(true){            while (selector.select()>0){//            因為有多個通道 ,所以采用集合 獲取所有就緒的通道                //        得到所有就緒狀態的通道集合到key中                Set<SelectionKey> selectionKeys = selector.selectedKeys(); //selectedKeys所有已經就緒的key集合//        轉成集合迭代器                Iterator<SelectionKey> iterator = selectionKeys.iterator();                while(iterator.hasNext()){                    SelectionKey selectionKey = iterator.next();                    //有人來連                    if(selectionKey.isAcceptable()){                        acceptOperator(serverSocketChannel,selector);                    }                    //發過來了已經                    else if(selectionKey.isReadable()){                        readOperator(selector,selectionKey);                    }                    //返回水表數據                    else if(selectionKey.isWritable()){                        writeOperator(selector,selectionKey);                    }                    iterator.remove();                }            }        }    }    //處理服務器寫事件    private void writeOperator(Selector selector,SelectionKey selectionKey) {        try {            //有channel可寫,取出可寫的channel            SocketChannel socketChannel = (SocketChannel) selectionKey.channel();            //                    設計非阻塞            socketChannel.configureBlocking(false);            socketChannel.write(Charset.forName("UTF-8").encode("數據庫存入成功!" ));            //重新將channel注冊到選擇器上,設計為監聽            socketChannel.register(selector,SelectionKey.OP_READ);        }catch (IOException e){            e.printStackTrace();        }    }    //    處理讀事件    private void readOperator(Selector selector, SelectionKey selectionKey) throws IOException {        try {            //                    獲取就緒通道            SocketChannel socketChannel = (SocketChannel)selectionKey.channel();//                    設計buffer            ByteBuffer buffer = ByteBuffer.allocate(1024);//                    循環讀客戶端數據            int length=0;            String msg="";            if((length=socketChannel.read(buffer))>0){  //讀到buffer里面//                        切換模式                buffer.flip();                msg+=Charset.forName("UTF-8").decode(buffer);  //從buffer里面取數據 解碼            }            System.out.println(msg);            String str[]=msg.split(":");            String temp=str[1];            String str2[]=temp.split("、");            SimpleDateFormat tempDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");            String datetime = tempDate.format(new java.util.Date());            JdbcUtil.find(new User(str2[0],str2[1],str2[2],datetime));            //重新將channel注冊到選擇器上,設計為監聽            socketChannel.register(selector,SelectionKey.OP_WRITE);        }catch (IOException e){            selectionKey.cancel();            selectionKey.channel().close();            System.out.println("有客戶端斷連,我已主動關閉");        }                        //光廣播到其他用戶上去//                        if(msg.length()>0){//                            System.out.println(msg);//                            castOtherClient(msg,selector,socketChannel);//                        }    }        //廣播到其他客戶端//    private void castOtherClient(String msg, Selector selector, SocketChannel socketChannel) throws IOException {////        //獲取所有就緒的channel//        Set selectionKeySet = selector.keys();//        循環處理搜索就緒的channel//        for (SelectionKey selectionKey : selectionKeySet){            獲取每一個channel//            Channel tarChannel = selectionKey.channel();//            不給自己發信息//            if(tarChannel instanceof SocketChannel && tarChannel!=socketChannel){//                ((SocketChannel)tarChannel).write(Charset.forName("UTF-8").encode(msg)); //傳輸數據是編碼,發送數據是解碼//            }//        }//    }    //處理接收狀態的通道    private void acceptOperator(ServerSocketChannel serverSocketChannel, Selector selector)  {        try {            //                    獲取連接            SocketChannel socketChannel = serverSocketChannel.accept();//                    設計非阻塞            socketChannel.configureBlocking(false);//                     注冊通道            socketChannel.register(selector,SelectionKey.OP_READ);            //回復客戶端消息            socketChannel.write(Charset.forName("UTF-8").encode("您已成功連接到服務器!"));        }catch (IOException e){            e.printStackTrace();        }    }    public static void main(String[] args) throws IOException {        new ChatServer().StratServer(7890);    }}

解釋:
其中我的readOperator函數是負責讀取客戶端傳來的信息。Nio編程核心是通道和選擇器,選擇器通過不斷輪詢,執行對應的函數。
此項目我加入了數據庫,如果收到客戶端信息,存入數據庫。

2、客戶端代碼

2.1、負責發送的主客戶端

package Client;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.SocketChannel;import java.nio.charset.Charset;import java.util.Scanner;public class ChatClient {    public void startClient(String name ) throws IOException, InterruptedException {        //        創建通道 綁定主機和端口        SocketChannel socketChannel = null;            socketChannel = SocketChannel.open(new InetSocketAddress(                    "127.0.0.1", 7890));        //接受服務端響應的數據        Selector selector = Selector.open();        socketChannel.configureBlocking(false);        socketChannel.register(selector, SelectionKey.OP_READ);        //創建線程        new Thread(new ClientThread(selector)).start();//負責拿到服務器端數據        //向服務端發送數據        System.out.println("請輸入抄水表編號、抄水量、抄表員(抄水時間自動生成)(請在1min中內完成)");        Scanner scanner = new Scanner(System.in);        while (scanner.hasNextLine()){            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);            String str = scanner.nextLine(); //鍵盤獲取輸入的內容            if(str.length()>0){               socketChannel.write(Charset.forName("UTF-8").encode("客戶端:"+name+":"+str+"(已加載數據庫)"));                //System.out.println(Charset.forName("UTF-8").encode(name+":"+str));            }        //設計非堵塞模式        socketChannel.configureBlocking(false);        //設計buffer    }    }    public static void main(String[] args) throws IOException, InterruptedException {        new ChatClient().startClient("gx");    }}

2.2、負責接收服務器信息的客戶端線程

package Client;import java.io.IOException;import java.net.ConnectException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.SocketChannel;import java.nio.charset.Charset;import java.util.Iterator;import java.util.Set;public class ClientThread implements Runnable{    private Selector selector;    ClientThread(Selector selector){        this.selector=selector;    }    @Override    public void run() {//        while(true){            for(;;){                try {                    int length=selector.select();                    if(length ==0){                        continue;                    }                    //        得到所有就緒狀態的通道集合到key中                    Set<SelectionKey> selectionKeys = selector.selectedKeys(); //selectedKeys所有已經就緒的key集合                    //        轉成集合迭代器                    Iterator<SelectionKey> iterator = selectionKeys.iterator();                    while(iterator.hasNext()){                        SelectionKey selectionKey = iterator.next();                        if(selectionKey.isReadable()){                            readOperator(selector,selectionKey);                        }                        iterator.remove();                    }                } catch (IOException | InterruptedException e) {                    e.printStackTrace();                }            }        }    //    處理接收服務器信息事件    private void readOperator(Selector selector, SelectionKey selectionKey) throws InterruptedException {        try {            //                    獲取就緒通道            SocketChannel socketChannel = (SocketChannel)selectionKey.channel();//                    設計buffer            ByteBuffer buffer = ByteBuffer.allocate(1024);//                    循環讀客戶端數據            int length=0;            String msg="";            if((length=socketChannel.read(buffer))>0){  //讀到buffer里面//                        切換模式                buffer.flip();                msg+= Charset.forName("UTF-8").decode(buffer);  //從buffer里面取數據 解碼            }            System.out.println(msg);            //重新將channel注冊到選擇器上,設計為監聽            socketChannel.register(selector,SelectionKey.OP_READ);        }catch (IOException e){            selectionKey.cancel();            System.out.println("服務器中斷 開始準備重連");            while (true){                try {                    new ChatClient().startClient("gx");                } catch (IOException ioException) {                    System.out.println("正在重連(5s) ");                    //ioException.printStackTrace();                    Thread.sleep(5000);                    continue;                }            }        }    }}

3、關鍵重連代碼解釋

1 重連代碼解釋

如果服務器突然關閉,如果在這里不try catch異常,而是向上拋出的話,隨著服務器異常關閉,客戶端也掛了,而且不會重連。
所以我們需要捕獲這個異常,并且開始不斷重連。
我寫了一個死循環,不斷連接,如果連不上他還是會報錯,所以連不上的錯也要捕獲異常,不然程序就報錯結束了,所以捕獲連接沒上的話,continue重新執行while循環,直到連接上服務器。

2 如果客戶端關閉 那么服務器也要主動關閉他

4 數據庫代碼及實體類:

如果還想實現數據庫方面代碼,私我

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/125587.html

相關文章

  • 一篇文章帶你徹底搞懂NIO

    摘要:阻塞當進行讀寫時,線程是阻塞的狀態。當任何一個收到數據后,中斷程序將喚起進程。接收數據當收到數據后,中斷程序會給的就緒列表添加引用。當接收到數據,中斷程序一方面修改,另一方面喚醒等待隊列中的進程,進程再次進入運行狀態如下圖。 本篇文章目的在于基本概念和原理的解釋,不會貼過多的使用代碼。 什么是NIO Java NIO (New IO)是 Java 的另一個 IO API (來自 jav...

    ziwenxie 評論0 收藏0
  • Java NIO淺析

    摘要:阻塞請求結果返回之前,當前線程被掛起。也就是說在異步中,不會對用戶線程產生任何阻塞。當前線程在拿到此次請求結果的過程中,可以做其它事情。事實上,可以只用一個線程處理所有的通道。 準備知識 同步、異步、阻塞、非阻塞 同步和異步說的是服務端消息的通知機制,阻塞和非阻塞說的是客戶端線程的狀態。已客戶端一次網絡請求為例做簡單說明: 同步同步是指一次請求沒有得到結果之前就不返回。 異步請求不會...

    yeooo 評論0 收藏0
  • 初探Java Socket

    摘要:綁定完成后允許套接字進行連接并等待連接。服務端根據報文返回響應,并關閉連接。單線程服務器多進程及多線程服務器復用服務器復用的多線程服務器單線程服務器一次只處理一個請求,直到其完成為止。 前言 本篇文章將涉及以下內容: IO實現Java Socket通信 NIO實現Java Socket通信 閱讀本文之前最好了解過: Java IO Java NIO Java Concurrenc...

    張漢慶 評論0 收藏0
  • java同步非阻塞IO

    摘要:的異步即是異步的,也是非阻塞的。但是,也可以進行一層稍微薄點的封裝,保留這種多路復用的模型,比如的,是一種同步非阻塞的模型。系統調用操作系統的系統調用提供了多路復用的非阻塞的系統調用,這也是機制實現需要用到的。 異步IO編程在javascript中得到了廣泛的應用,之前也寫過一篇博文進行梳理。js的異步IO即是異步的,也是非阻塞的。非阻塞的IO需要底層操作系統的支持,比如在linux上...

    caoym 評論0 收藏0
  • 少啰嗦!一分鐘帶你讀懂JavaNIO和經典IO的區別

    摘要:的選擇器允許單個線程監視多個輸入通道。一旦執行的線程已經超過讀取代碼中的某個數據片段,該線程就不會在數據中向后移動通常不會。 1、引言 很多初涉網絡編程的程序員,在研究Java NIO(即異步IO)和經典IO(也就是常說的阻塞式IO)的API時,很快就會發現一個問題:我什么時候應該使用經典IO,什么時候應該使用NIO? 在本文中,將嘗試用簡明扼要的文字,闡明Java NIO和經典IO之...

    Meils 評論0 收藏0

發表評論

0條評論

不知名網友

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<