在练习使用nio时,无意中好像发现一个bug
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在练习使用nio时,无意中好像发现一个bug相关的知识,希望对你有一定的参考价值。
就是我在看netty权威指南时,里面有个TimeServer的例子,然后按着上面的写了,在用到Nio时,我用客户端向服务端发送字符串“date”、“d"、"da"、”dat“等字符串时,发送不成功。然而发送其它字符时会成功。然后用netty时也是如此
下面是我的例子,请高手解答
TimeServer:
1 package com.szc.nio; 2 3 import java.io.IOException; 4 5 /** 6 * @author hz17052992 7 * @date 2017年6月12日 上午11:13:40 8 * @version 9 */ 10 public class TimeServer { 11 12 public static final int DEFAULT_PORT = 8080; 13 14 public static void main(String[] args) throws IOException { 15 int port = DEFAULT_PORT; 16 if(args != null && args.length > 0) { 17 try { 18 port = Integer.valueOf(args[0]); 19 } catch (NumberFormatException e) { 20 port = DEFAULT_PORT; 21 } 22 23 } 24 25 MultiplexerTimerServer timeServer = new MultiplexerTimerServer(port); 26 new Thread(timeServer, "NIO-MultiplexerServer-001").start(); 27 } 28 } 29
MultiplexerTimerServer:
1 package com.szc.nio; 2 3 import java.io.IOException; 4 import java.net.InetSocketAddress; 5 import java.nio.ByteBuffer; 6 import java.nio.channels.SelectionKey; 7 import java.nio.channels.Selector; 8 import java.nio.channels.ServerSocketChannel; 9 import java.nio.channels.SocketChannel; 10 import java.util.Date; 11 import java.util.Iterator; 12 import java.util.Set; 13 14 /** 15 * 多路利用类,轮询利用器 处理多连接 16 * 17 * @author hz17052992 18 * @date 2017年6月12日 下午3:38:45 19 * @version 20 */ 21 public class MultiplexerTimerServer implements Runnable { 22 23 private Selector selector; 24 25 private ServerSocketChannel server; 26 27 private volatile boolean stop; 28 29 public MultiplexerTimerServer(int port) { 30 try { 31 selector = Selector.open(); 32 server = ServerSocketChannel.open(); 33 // 绑定端口 34 server.configureBlocking(false); 35 server.socket().bind(new InetSocketAddress(port), 1024); 36 // 注册到selector,并监听连接事件 37 server.register(selector, SelectionKey.OP_ACCEPT); 38 System.out.println("the time server is started in port:" + port); 39 } catch (IOException e) { 40 e.printStackTrace(); 41 System.exit(-1); 42 } 43 44 } 45 46 public void stop() { 47 stop = true; 48 } 49 50 @Override 51 public void run() { 52 while (!stop) { 53 SelectionKey key = null; 54 try { 55 selector.select(1000); 56 Set<SelectionKey> keysSet = selector.selectedKeys(); 57 Iterator<SelectionKey> it = keysSet.iterator(); 58 while (it.hasNext()) { 59 key = it.next(); 60 it.remove(); 61 handleInput(key); 62 } 63 } catch (IOException e) { 64 if(key != null) { 65 key.cancel(); 66 if(key.channel() != null) { 67 try { 68 key.channel().close(); 69 } catch (IOException e1) { 70 e1.printStackTrace(); 71 } 72 } 73 } 74 75 e.printStackTrace(); 76 } 77 } 78 79 if (selector != null) { 80 try { 81 selector.close(); 82 } catch (IOException e) { 83 84 e.printStackTrace(); 85 } 86 } 87 } 88 89 /** 90 * 91 * @param key 92 * 93 * @author hz17052992 94 * @date 2017年6月12日 下午4:49:07 95 * @version 96 * @throws IOException 97 */ 98 private void handleInput(SelectionKey key) throws IOException { 99 if (key.isValid()) { 100 // 处理连接 101 if (key.isAcceptable()) { 102 // 得到server 103 ServerSocketChannel ssc = (ServerSocketChannel) key.channel(); 104 try { 105 SocketChannel sc = ssc.accept(); 106 // 设置成非阻塞,并且注册到selector上监听读事件 107 sc.configureBlocking(false); 108 // sc.register(selector, SelectionKey.OP_WRITE); 109 sc.register(selector, SelectionKey.OP_READ); 110 // ssc.register(selector, SelectionKey.OP_READ); 111 } catch (IOException e) { 112 113 e.printStackTrace(); 114 } 115 } 116 117 if (key.isReadable()) { 118 SocketChannel sc = (SocketChannel) key.channel(); 119 ByteBuffer buffer = ByteBuffer.allocate(1024); 120 int bytes = sc.read(buffer); 121 if (bytes > 0) { 122 buffer.flip(); 123 byte[] b = new byte[buffer.remaining()]; 124 buffer.get(b); 125 String body = new String(b, "UTF-8"); 126 System.out.println("the time server recieve order:" + body); 127 String currentTime = "date".equalsIgnoreCase(body) ? new Date(System.currentTimeMillis()).toString() : "Bad Order"; 128 doWrite(sc, currentTime); 129 } else { 130 key.cancel(); 131 sc.close(); 132 } 133 } 134 } 135 } 136 137 private void doWrite(SocketChannel sc, String message) throws IOException { 138 if (message != null && !message.isEmpty()) { 139 byte[] b = message.getBytes(); 140 ByteBuffer buffer = ByteBuffer.allocate(b.length); 141 buffer.put(b); 142 buffer.flip(); 143 sc.write(buffer); 144 } 145 } 146 }
TimeCilent:
1 package com.szc.nio; 2 3 4 /** 5 * @author hz17052992 6 * @date 2017年6月12日 下午1:38:35 7 * @version 8 */ 9 public class TimeCilent { 10 11 public static void main(String[] args) { 12 int port = 8080; 13 if(args != null && args.length > 0) { 14 try { 15 port = Integer.valueOf(args[0]); 16 } catch (NumberFormatException e) { 17 port = 8080; 18 } 19 20 } 21 new Thread(new TimeClientHandler("127.0.0.1", port)).start(); 22 } 23 }
TimeClientHandler:
1 package com.szc.nio; 2 3 import java.io.IOException; 4 import java.net.InetSocketAddress; 5 import java.nio.ByteBuffer; 6 import java.nio.channels.SelectionKey; 7 import java.nio.channels.Selector; 8 import java.nio.channels.SocketChannel; 9 import java.util.Iterator; 10 import java.util.Set; 11 12 /** 13 * @author hz17052992 14 * @date 2017年6月12日 下午5:37:35 15 * @version 16 */ 17 public class TimeClientHandler implements Runnable { 18 19 private String host; 20 21 private int port; 22 23 private SocketChannel socketChannel; 24 25 private Selector selector; 26 27 private volatile boolean stop = false; 28 29 public TimeClientHandler(String host, int port) { 30 this.host = host; 31 this.port = port; 32 try { 33 selector = Selector.open(); 34 socketChannel = SocketChannel.open(); 35 socketChannel.configureBlocking(false); 36 // doConnect(); 37 } catch (IOException e) { 38 e.printStackTrace(); 39 System.exit(-1); 40 } 41 42 } 43 44 @Override 45 public void run() { 46 try { 47 doConnect(); 48 } catch (IOException e) { 49 e.printStackTrace(); 50 System.exit(-1); 51 } 52 53 while (!stop) { 54 SelectionKey key = null; 55 try { 56 selector.select(1000); 57 Set<SelectionKey> keysSet = selector.selectedKeys(); 58 Iterator<SelectionKey> it = keysSet.iterator(); 59 while (it.hasNext()) { 60 key = it.next(); 61 it.remove(); 62 handleInput(key); 63 } 64 } catch (IOException e) { 65 if (key != null) { 66 key.cancel(); 67 if (key.channel() != null) { 68 try { 69 key.channel().close(); 70 } catch (IOException e1) { 71 e1.printStackTrace(); 72 } 73 } 74 } 75 e.printStackTrace(); 76 } 77 } 78 79 if (selector != null) { 80 try { 81 selector.close(); 82 } catch (IOException e) { 83 84 e.printStackTrace(); 85 } 86 } 87 } 88 89 private void handleInput(SelectionKey key) throws IOException { 90 if (key.isValid()) { 91 // 处理连接 92 SocketChannel sc = (SocketChannel) key.channel(); 93 if (key.isConnectable()) { 94 95 if (sc.finishConnect()) { 96 // sc.configureBlocking(false); 97 sc.register(selector, SelectionKey.OP_READ); 98 doWrite(sc); 99 } 100 } 101 102 if (key.isReadable()) { 103 // SocketChannel sc = (SocketChannel) key.channel(); 104 ByteBuffer buffer = ByteBuffer.allocate(1024); 105 int bytes = sc.read(buffer); 106 if (bytes > 0) { 107 buffer.flip(); 108 byte[] b = new byte[buffer.remaining()]; 109 buffer.get(b); 110 String body = new String(b, "UTF-8"); 111 System.out.println("Now is:" + body); 112 113 } else if (bytes < 0) { 114 key.cancel(); 115 sc.close(); 116 } 117 } 118 119 if (key.isWritable()) { 120 System.out.println("write"); 121 } 122 } 123 } 124 125 private void doConnect() throws IOException { 126 if (socketChannel.connect(new InetSocketAddress(host, port))) { 127 socketChannel.register(selector, SelectionKey.OP_READ); 128 doWrite(socketChannel); 129 } else { 130 socketChannel.register(selector, SelectionKey.OP_CONNECT); 131 } 132 133 } 134 /** 135 private void doWrite(SocketChannel socketChannel) throws IOException { 136 byte[] b = "date".getBytes(); 137 ByteBuffer buffer = ByteBuffer.allocate(b.length); 138 buffer.put(b); 139 buffer.flip(); 140 socketChannel.write(buffer); 141 if (!buffer.hasRemaining()) { 142 System.out.println("Sender order to server succeed."); 143 } 144 } 145 */ 146 147 private void doWrite(SocketChannel socketChannel) throws IOException { 148 /** 149 * 发送 "d","da","date"等字符串时不成功,如果改为其它 如query时,就会成功 150 */ 151 byte[] b = "date".getBytes(); 152 ByteBuffer buffer = ByteBuffer.allocate(b.length); 153 //buffer.clear(); 154 buffer.put(b); 155 buffer.flip(); 156 socketChannel.write(buffer); 157 //buffer.flip(); 158 if (!buffer.hasRemaining()) { 159 System.out.println("Send order 2 server succeed."); 160 } 161 } 162 163 }
以上是关于在练习使用nio时,无意中好像发现一个bug的主要内容,如果未能解决你的问题,请参考以下文章
虚拟机中Ubuntu与金山毒霸的冲突 影响Ctrl+C和鼠标选中就被复制.
bug记录----Java NIO 报java.nio.charset.MalformedInputException: Input length = 1