首页 > 代码库 > 在练习使用nio时,无意中好像发现一个bug

在练习使用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  
View Code

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 }
View Code

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 }
View Code

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 }
View Code

 

在练习使用nio时,无意中好像发现一个bug