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

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

lease 自己 ret http try star 復用器 election mov

在做關於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 }

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

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