在做關於NIO TCP編程小案例時遇到無法監聽write的問題,沒想到只是我的if語句的位置放錯了位置,哎,看了半天沒看出來

来源:https://www.cnblogs.com/Meiwah/archive/2019/02/22/10416092.html
-Advertisement-
Play Games

在做關於NIO TCP編程小案例時遇到無法監聽write的問題,沒想到只是我的if語句的位置放錯了位置,哎,看了半天沒看出來 貼下課堂筆記: 在Java中使用NIO進行網路TCP套接字編程主要以下幾個類: ServerSocketChannel: 服務端套接字通道,主要監聽接收客戶端請求 Selec ...


在做關於NIO TCP編程小案例時遇到無法監聽write的問題,沒想到只是我的if語句的位置放錯了位置,哎,看了半天沒看出來

貼下課堂筆記

Java中使用NIO進行網路TCP套接字編程主要以下幾個類:

ServerSocketChannel: 服務端套接字通道,主要監聽接收客戶端請求

Selector:通道選擇器,主要用於管理服務端通道和所有客戶端通道(監聽通道中發生的事件),也就說是一個多路通道復用器。

SelectorKey: 事件選擇鍵

SocketChannel: 套接字通道(客戶端)

這篇文章《NIO編程中的SelectionKey.interestOps方法中的邏輯運算》解決了我一些疑問,地址:https://blog.csdn.net/woaiqianzhige/article/details/78696188

NIO 套接字服務端開發步驟:

  1. 創建選擇器
  2. 啟動服務端通道
  3. 設置服務端通道為非阻塞模式
  4. 將服務端通道註冊到選擇器
  5. 輪訓通道事件
  6. 處理通道事件
  7. 關閉通道(可選)

案例:服務端接收客戶端發送的簡訊息,服務端回覆已收到。

服務端代碼:

 

  1 import java.io.IOException;
  2 import java.net.InetSocketAddress;
  3 import java.nio.ByteBuffer;
  4 import java.nio.channels.ClosedChannelException;
  5 import java.nio.channels.SelectionKey;
  6 import java.nio.channels.Selector;
  7 import java.nio.channels.ServerSocketChannel;
  8 import java.nio.channels.SocketChannel;
  9 import java.util.Iterator;
 10 import java.util.Set;
 11 
 12 public class Server {
 13     private Selector selector;
 14     private ServerSocketChannel serverSocketChannel;
 15     private ByteBuffer byteBuffer = ByteBuffer.allocate(8192);
 16 
 17     /**
 18      * 構造方法 啟動伺服器
 19      * 
 20      * @param port
 21      * @throws IOException
 22      */
 23     public Server() {
 24         try {
 25             selector = Selector.open();
 26             serverSocketChannel = ServerSocketChannel.open();
 27             serverSocketChannel.configureBlocking(false);
 28             serverSocketChannel.bind(new InetSocketAddress(10086));
 29             serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
 30             System.out.println("Server start successful with port: 10086");
 31         } catch (ClosedChannelException e) {
 32             e.printStackTrace();
 33         } catch (IOException e) {
 34             e.printStackTrace();
 35         }
 36     }
 37 
 38     public static void main(String[] args) throws Exception {
 39         new Server().start();
 40     }
 41 
 42     private void start() {
 43         while (true) {
 44             try {
 45                 selector.select();
 46                 Set<SelectionKey> keys = selector.selectedKeys();
 47                 Iterator<SelectionKey> keyIterator = keys.iterator();
 48                 while (keyIterator.hasNext()) {
 49                     SelectionKey key = keyIterator.next();
 50                     keyIterator.remove();
 51                     if (!key.isValid()) {
 52                         continue;
 53                     }
 54                     if (key.isAcceptable()) {
 55                         accept(key);
 56                     }
 57                     if (key.isReadable()) {
 58                         receive(key);
 59                     }
 60                     if (key.isWritable()) {
 61                         reply(key);
 62                     }
 63                 }
 64             } catch (IOException e) {
 65                 e.printStackTrace();
 66             } catch (Exception e) {
 67                 e.printStackTrace();
 68             }
 69         }
 70     }
 71 
 72     private void reply(SelectionKey key) {
 73         try {
 74             SocketChannel socketChannel = (SocketChannel) key.channel();
 75             byteBuffer.clear();
 76             String message = "receive success";
 77             byteBuffer.put(message.getBytes());
 78             byteBuffer.flip();
 79             socketChannel.write(byteBuffer);
 80             System.out.println("reply:" + message);
 81             byteBuffer.clear();
 82             key.interestOps(SelectionKey.OP_READ);
 83         } catch (IOException e) {
 84             e.printStackTrace();
 85         }
 86     }
 87 
 88     private void receive(SelectionKey key) {
 89         try {
 90             SocketChannel socketChannel = (SocketChannel) key.channel();
 91             byteBuffer.clear();
 92             int flag = socketChannel.read(byteBuffer);
 93             if (flag == -1) {
 94                 key.channel().close();
 95                 key.cancel();
 96                 return;
 97             }
 98             byteBuffer.flip();
 99             byte[] buf = new byte[byteBuffer.remaining()];
100             byteBuffer.get(buf);
101             String message = new String(buf);
102             System.out.println("receive message:" + message);
103             byteBuffer.clear();
104             key.interestOps(SelectionKey.OP_WRITE);
105         } catch (IOException e) {
106             e.printStackTrace();
107         }
108     }
109 
110     private void accept(SelectionKey key) {
111         try {
112             SocketChannel socketChannel = serverSocketChannel.accept();
113             socketChannel.configureBlocking(false);
114             socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
115             System.out.println(Thread.currentThread().getName() + ": create client channel.");
116         } catch (ClosedChannelException e) {
117             e.printStackTrace();
118         } catch (IOException e) {
119             e.printStackTrace();
120         }
121     }
122 }

 

客戶端代碼:

 1 import java.io.IOException;
 2 import java.net.InetSocketAddress;
 3 import java.nio.ByteBuffer;
 4 import java.nio.channels.ClosedChannelException;
 5 import java.nio.channels.SelectionKey;
 6 import java.nio.channels.Selector;
 7 import java.nio.channels.SocketChannel;
 8 import java.util.Iterator;
 9 import java.util.Scanner;
10 
11 public class Client {
12     private Selector selector;
13     private ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
14     private SocketChannel socketChannel;
15 
16     public Client() {
17         try {
18             selector = Selector.open();
19             socketChannel = SocketChannel.open();
20             socketChannel.configureBlocking(false);
21             socketChannel.register(selector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ | SelectionKey.OP_WRITE);
22             socketChannel.connect(new InetSocketAddress("127.0.0.1", 10086));
23             System.out.println("Client start successful");
24         } catch (ClosedChannelException e) {
25             e.printStackTrace();
26         } catch (IOException e) {
27             e.printStackTrace();
28         }
29     }
30 
31     public static void main(String[] args) {
32         new Client().start();    
33     }
34 
35     private void start() {
36         while (true) {
37             try {
38                 selector.select();
39                 Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
40                 while (keys.hasNext()) {
41                     SelectionKey key = keys.next();
42                     keys.remove();
43                     if (!key.isValid()) {
44                         continue;
45                     }
46                     if (key.isConnectable()) {
47                         if (socketChannel.finishConnect()) {
48                             key.interestOps(key.interestOps() & ~SelectionKey.OP_CONNECT);
49                             System.out.println("Client connect server success");
50                         }
51                     }
52                     if (key.isReadable()) {
53                         receive(key);
54                     }
55                     if (key.isWritable()) {
56                         reply(key);
57                     }
58                 }
59             } catch (Exception e) {
60                 e.printStackTrace();
61             }
62         }
63     }
64 
65     private void reply(SelectionKey key) {
66         try {
67             @SuppressWarnings("resource")
68             Scanner scanner = new Scanner(System.in);
69             byteBuffer.clear();
70             System.out.println("please input message:");
71             String message = scanner.next();
72             byteBuffer.put(message.getBytes());
73             byteBuffer.flip();
74             socketChannel.write(byteBuffer);
75             byteBuffer.clear();
76             System.out.println("send message:" + message);
77             key.interestOps(SelectionKey.OP_READ);
78         } catch (IOException e) {
79             e.printStackTrace();
80         }
81     }
82 
83     private void receive(SelectionKey key) {
84         try {
85             byteBuffer.clear();
86             socketChannel.read(byteBuffer);
87             byteBuffer.flip();
88             byte[] bytes = new byte[byteBuffer.remaining()];
89             byteBuffer.get(bytes);
90             String message = new String(bytes).trim();
91             System.out.println("receive message: " + message);
92             byteBuffer.clear();
93             key.interestOps(SelectionKey.OP_WRITE);
94         } catch (IOException e) {
95             e.printStackTrace();
96         }
97     }
98 }

真是粗心大意了。。。特發此博文給我自己漲漲記性

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 實現效果是在要素點的四周不同位置添加標簽。 此節需要註意一個問題,書寫的先後順序可能會影響運行速度。要註意正確的書寫先後。 1、定義涉及到的所有變數 var minScale = 2500000; var serviceUrl = "https://services.arcgis.com/V6ZHF ...
  • js String擴展方法 'asdasdasd'.repalceA()"AsdAsdAsd" ...
  • 簡介 處理併發問題的重點不在於你的設計是怎樣的,而在於你要評估你的併發,併在併發範圍內處理。你預估你的併發是多少,然後測試r+m是否支持。緩存的目的是為了應對普通對象資料庫的讀寫限制,依托與nosql的優勢進行高速讀寫。 redis本身也有併發瓶頸。所以你要把讀寫和併發區分開來處理。只讀業務是不是可 ...
  • [TOC] JSON Web Token(縮寫 JWT)是目前最流行的跨域認證解決方案,本文介紹它的原理和用法。 一、跨域認證的問題 互聯網服務離不開用戶認證。一般流程是下麵這樣。 1. 用戶向伺服器發送用戶名和密碼。 2. 伺服器驗證通過後,在當前對話(session)裡面保存相關數據,比如用戶角 ...
  • Python環境的安裝 安裝Python: windows: 1、下載安裝包 https://www.python.org/downloads/ 2、安裝 預設安裝路徑:C:\python27 3、配置環境變數 【右鍵電腦】--》【屬性】--》【高級系統設置】--》【高級】--》【環境變數】--》 ...
  • 前言 開心一刻 一名劫匪慌忙中竄上了一輛車的後座,上車後發現主駕和副駕的一男一女疑惑地回頭看著他,他立即拔出槍威脅到:“趕快開車,甩掉後面的警車,否則老子一槍崩了你!”,於是副駕上的男人轉過臉對那女的說:“大姐,別慌,聽我口令把剛纔的動作再練習一遍,掛一檔,輕鬆離合,輕踩油門,走...走,哎 走.. ...
  • 題意 "題目鏈接" 有$n$個位置,每次你需要以$1 \sim n 1$的一個排列的順序去染每一個顏色,第$i$個數可以把$i$和$i+1$位置染成黑色。一個排列的價值為最早把所有位置都染成黑色的次數。問所有排列的分數之和 Sol 神仙題Orz 不難想到我們可以枚舉染色的次數$i \in [\lce ...
  • 《數據結構》這門課程的安排,就要開始各種演算法和數構的燒腦學習了,從最簡單的應用題型入手吧。 本題要求你寫個程式把給定的符號列印成沙漏的形狀。例如給定17個“*”,要求按下列格式列印 所謂“沙漏形狀”,是指每行輸出奇數個符號;各行符號中心對齊;相鄰兩行符號數差2;符號數先從大到小順序遞減到1,再從小到 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...