在做關於NIO TCP編程小案例時遇到無法監聽write的問題,沒想到只是我的if語句的位置放錯了位置,哎,看了半天沒看出來
阿新 • • 發佈:2019-02-22
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 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語句的位置放錯了位置,哎,看了半天沒看出來