JAVA NIO 服务器与客户端实现示例(代码1)

来源:互联网 发布:mac如何解压zip文件 编辑:程序博客网 时间:2024/06/05 00:53

感谢有奉献精神的人

转自:http://blog.csdn.net/zmx729618/article/details/54584583


Java NIO系列教程:http://ifeve.com/overview/


公共类:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片在CODE上查看代码片派生到我的代码片
  1. package com.stevex.app.nio;  
  2.    
  3. import java.nio.ByteBuffer;  
  4. import java.nio.CharBuffer;  
  5. import java.nio.charset.CharacterCodingException;  
  6. import java.nio.charset.Charset;  
  7. import java.nio.charset.CharsetDecoder;  
  8. import java.nio.charset.CharsetEncoder;  
  9.    
  10. public class CharsetHelper {  
  11.     private static final String UTF_8 = "UTF-8";  
  12.     private static CharsetEncoder encoder = Charset.forName(UTF_8).newEncoder();  
  13.     private static CharsetDecoder decoder = Charset.forName(UTF_8).newDecoder();  
  14.        
  15.     public static ByteBuffer encode(CharBuffer in) throws CharacterCodingException{  
  16.         return encoder.encode(in);  
  17.     }  
  18.    
  19.     public static CharBuffer decode(ByteBuffer in) throws CharacterCodingException{  
  20.         return decoder.decode(in);  
  21.     }  
  22. }  

服务器代码:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片在CODE上查看代码片派生到我的代码片
  1. package com.stevex.app.nio;  
  2.    
  3. import java.io.IOException;  
  4. import java.net.InetSocketAddress;  
  5. import java.nio.ByteBuffer;  
  6. import java.nio.CharBuffer;  
  7. import java.nio.channels.ClosedChannelException;  
  8. import java.nio.channels.SelectionKey;  
  9. import java.nio.channels.Selector;  
  10. import java.nio.channels.ServerSocketChannel;  
  11. import java.nio.channels.SocketChannel;  
  12. import java.util.Iterator;  
  13.    
  14. public class XiaoNa {  
  15.     private ByteBuffer readBuffer;  
  16.     private Selector selector;  
  17.        
  18.     public static void main(String[] args){  
  19.         XiaoNa xiaona = new XiaoNa();  
  20.         xiaona.init();  
  21.         xiaona.listen();  
  22.     }  
  23.        
  24.     private void init(){  
  25.         readBuffer = ByteBuffer.allocate(1024);  
  26.         ServerSocketChannel servSocketChannel;  
  27.            
  28.         try {  
  29.             servSocketChannel = ServerSocketChannel.open();  
  30.             servSocketChannel.configureBlocking(false);  
  31.             //绑定端口  
  32.             servSocketChannel.socket().bind(new InetSocketAddress(8383));  
  33.                
  34.             selector = Selector.open();  
  35.             servSocketChannel.register(selector, SelectionKey.OP_ACCEPT);  
  36.         } catch (IOException e) {  
  37.             e.printStackTrace();  
  38.         }        
  39.     }  
  40.    
  41.     private void listen() {  
  42.         while(true){  
  43.             try{  
  44.                 selector.select();               
  45.                 Iterator ite = selector.selectedKeys().iterator();  
  46.                    
  47.                 while(ite.hasNext()){  
  48.                     SelectionKey key = (SelectionKey) ite.next();                    
  49.                     ite.remove();//确保不重复处理  
  50.                        
  51.                     handleKey(key);  
  52.                 }  
  53.             }  
  54.             catch(Throwable t){  
  55.                 t.printStackTrace();  
  56.             }                            
  57.         }                
  58.     }  
  59.    
  60.     private void handleKey(SelectionKey key)  
  61.             throws IOException, ClosedChannelException {  
  62.         SocketChannel channel = null;  
  63.            
  64.         try{  
  65.             if(key.isAcceptable()){  
  66.                 ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();  
  67.                 channel = serverChannel.accept();//接受连接请求  
  68.                 channel.configureBlocking(false);  
  69.                 channel.register(selector, SelectionKey.OP_READ);  
  70.             }  
  71.             else if(key.isReadable()){  
  72.                 channel = (SocketChannel) key.channel();  
  73.                 readBuffer.clear();  
  74.                 /*当客户端channel关闭后,会不断收到read事件,但没有消息,即read方法返回-1 
  75.                  * 所以这时服务器端也需要关闭channel,避免无限无效的处理*/                
  76.                 int count = channel.read(readBuffer);  
  77.                    
  78.                 if(count > 0){  
  79.                     //一定需要调用flip函数,否则读取错误数据  
  80.                     readBuffer.flip();  
  81.                     /*使用CharBuffer配合取出正确的数据 
  82.                     String question = new String(readBuffer.array());   
  83.                     可能会出错,因为前面readBuffer.clear();并未真正清理数据 
  84.                     只是重置缓冲区的position, limit, mark, 
  85.                     而readBuffer.array()会返回整个缓冲区的内容。 
  86.                     decode方法只取readBuffer的position到limit数据。 
  87.                     例如,上一次读取到缓冲区的是"where", clear后position为0,limit为 1024, 
  88.                     再次读取“bye"到缓冲区后,position为3,limit不变, 
  89.                     flip后position为0,limit为3,前三个字符被覆盖了,但"re"还存在缓冲区中, 
  90.                     所以 new String(readBuffer.array()) 返回 "byere", 
  91.                     而decode(readBuffer)返回"bye"。             
  92.                     */  
  93.                     CharBuffer charBuffer = CharsetHelper.decode(readBuffer);   
  94.                     String question = charBuffer.toString();   
  95.                     String answer = getAnswer(question);  
  96.                     channel.write(CharsetHelper.encode(CharBuffer.wrap(answer)));  
  97.                 }  
  98.                 else{  
  99.                     //这里关闭channel,因为客户端已经关闭channel或者异常了  
  100.                     channel.close();                 
  101.                 }                        
  102.             }  
  103.         }  
  104.         catch(Throwable t){  
  105.             t.printStackTrace();  
  106.             if(channel != null){  
  107.                 channel.close();  
  108.             }  
  109.         }        
  110.     }  
  111.        
  112.     private String getAnswer(String question){  
  113.         String answer = null;  
  114.            
  115.         switch(question){  
  116.         case "who":  
  117.             answer = "我是小娜\n";  
  118.             break;  
  119.         case "what":  
  120.             answer = "我是来帮你解闷的\n";  
  121.             break;  
  122.         case "where":  
  123.             answer = "我来自外太空\n";  
  124.             break;  
  125.         case "hi":  
  126.             answer = "hello\n";  
  127.             break;  
  128.         case "bye":  
  129.             answer = "88\n";  
  130.             break;  
  131.         default:  
  132.                 answer = "请输入 who, 或者what, 或者where";  
  133.         }  
  134.            
  135.         return answer;  
  136.     }  
  137. }  

客户端代码:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片在CODE上查看代码片派生到我的代码片
  1. package com.stevex.app.nio;  
  2.    
  3. import java.io.IOException;  
  4. import java.net.InetSocketAddress;  
  5. import java.nio.ByteBuffer;  
  6. import java.nio.CharBuffer;  
  7. import java.nio.channels.SelectionKey;  
  8. import java.nio.channels.Selector;  
  9. import java.nio.channels.SocketChannel;  
  10. import java.util.Iterator;  
  11. import java.util.Random;  
  12. import java.util.concurrent.ArrayBlockingQueue;  
  13. import java.util.concurrent.BlockingQueue;  
  14. import java.util.concurrent.TimeUnit;  
  15.    
  16.    
  17. public class Client implements Runnable{  
  18.     private BlockingQueue<String> words;  
  19.     private Random random;  
  20.        
  21.     public static void main(String[] args) {        
  22.         //种多个线程发起Socket客户端连接请求  
  23.         for(int i=0; i<10; i++){  
  24.             Client c = new Client();  
  25.             c.init();  
  26.             new Thread(c).start();  
  27.         }        
  28.     }  
  29.    
  30.     @Override  
  31.     public void run() {       
  32.         SocketChannel channel = null;  
  33.         Selector selector = null;  
  34.         try {  
  35.             channel = SocketChannel.open();  
  36.             channel.configureBlocking(false);  
  37.             //请求连接  
  38.             channel.connect(new InetSocketAddress("localhost"8383));  
  39.             selector = Selector.open();  
  40.             channel.register(selector, SelectionKey.OP_CONNECT);  
  41.             boolean isOver = false;  
  42.                
  43.             while(! isOver){  
  44.                 selector.select();  
  45.                 Iterator ite = selector.selectedKeys().iterator();  
  46.                 while(ite.hasNext()){  
  47.                     SelectionKey key = (SelectionKey) ite.next();  
  48.                     ite.remove();  
  49.                        
  50.                     if(key.isConnectable()){  
  51.                         if(channel.isConnectionPending()){  
  52.                             if(channel.finishConnect()){  
  53.                                 //只有当连接成功后才能注册OP_READ事件  
  54.                                 key.interestOps(SelectionKey.OP_READ);  
  55.                                    
  56.                                 channel.write(CharsetHelper.encode(CharBuffer.wrap(getWord())));  
  57.                                 sleep();  
  58.                             }  
  59.                             else{  
  60.                                 key.cancel();  
  61.                             }  
  62.                         }                                                
  63.                     }  
  64.                     else if(key.isReadable()){  
  65.                         ByteBuffer byteBuffer = ByteBuffer.allocate(128);                         
  66.                         channel.read(byteBuffer);  
  67.                         byteBuffer.flip();  
  68.                         CharBuffer charBuffer = CharsetHelper.decode(byteBuffer);  
  69.                         String answer = charBuffer.toString();   
  70.                         System.out.println(Thread.currentThread().getId() + "---" + answer);  
  71.                            
  72.                         String word = getWord();  
  73.                         if(word != null){  
  74.                             channel.write(CharsetHelper.encode(CharBuffer.wrap(word)));  
  75.                         }  
  76.                         else{  
  77.                             isOver = true;  
  78.                         }  
  79.                         sleep();                         
  80.                     }  
  81.                 }  
  82.             }                            
  83.         } catch (IOException e) {  
  84.             e.printStackTrace();  
  85.         }  
  86.         finally{  
  87.             if(channel != null){  
  88.                 try {  
  89.                     channel.close();  
  90.                 } catch (IOException e) {                        
  91.                     e.printStackTrace();  
  92.                 }                    
  93.             }  
  94.                
  95.             if(selector != null){  
  96.                 try {  
  97.                     selector.close();  
  98.                 } catch (IOException e) {  
  99.                     e.printStackTrace();  
  100.                 }  
  101.             }  
  102.         }  
  103.     }  
  104.    
  105.     private void init() {  
  106.         words = new ArrayBlockingQueue<String>(5);  
  107.         try {  
  108.             words.put("hi");  
  109.             words.put("who");  
  110.             words.put("what");  
  111.             words.put("where");  
  112.             words.put("bye");  
  113.         } catch (InterruptedException e) {  
  114.             e.printStackTrace();  
  115.         }    
  116.            
  117.         random = new Random();  
  118.     }  
  119.        
  120.     private String getWord(){  
  121.         return words.poll();  
  122.     }  
  123.    
  124.     private void sleep() {  
  125.         try {  
  126.             TimeUnit.SECONDS.sleep(random.nextInt(3));  
  127.         } catch (InterruptedException e) {  
  128.             e.printStackTrace();  
  129.         }  
  130.     }    
  131.        
  132.     private void sleep(long l) {  
  133.         try {  
  134.             TimeUnit.SECONDS.sleep(l);  
  135.         } catch (InterruptedException e) {  
  136.             e.printStackTrace();  
  137.         }  
  138.     }  
  139. }  


原创粉丝点击