nio socket 及其开源框架MINA学习总结(一)

来源:互联网 发布:js模块化 编辑:程序博客网 时间:2024/04/30 12:43

nio socket 及其开源框架MINA学习总结(一)

关键字:   nio socket MINA    

最近花了点时间研究了一下nio,及其开源框架MINA,现把心得总结如下:

1:传统socket:阻塞式通信

每建立一个Socket连接时,同时创建一个新线程对该Socket进行单独通信(采用阻塞的方式通信)。这种方式具有很高的响应速度,并且控制起来也很简单,在连接数较少的时候非常有效,但是如果对每一个连接都产生一个线程的无疑是对系统资源的一种浪费,如果连接数较多将会出现资源不足的情况。

example:
server code:

java 代码
  1. public class MultiUserServer extends Thread {   
  2.     private Socket client;   
  3.        
  4.     public MultiUserServer(Socket c) {   
  5.         this.client = c;   
  6.     }   
  7.   
  8.     public void run() {   
  9.         try {   
  10.             BufferedReader in = new BufferedReader(new InputStreamReader(client   
  11.                     .getInputStream()));   
  12.             PrintWriter out = new PrintWriter(client.getOutputStream());   
  13.             //  Mutil User but can't parallel   
  14.             while (true) {   
  15.                 String str = in.readLine();   
  16.                 System.out.println(str);   
  17.                 SocketLog.debug("receive message: " + str);   
  18.                 out.println("has receive....");   
  19.                 out.flush();   
  20.                 if (str.equals("end"))   
  21.                     break;   
  22.             }   
  23.             client.close();   
  24.         } catch (IOException ex) {   
  25.         }    
  26.     }   
  27.   
  28.     public static void main(String[] args) throws IOException {   
  29.         int port = 5678;   
  30.         if (args.length > 0)   
  31.             port = Integer.parseInt(args[0]);   
  32.         ServerSocket server = new ServerSocket(port);   
  33.         SocketLog.debug("the server socket application is created!");   
  34.         while (true) {   
  35.             //  transfer location change Single User or Multi User   
  36.             MultiUserServer mu = new MultiUserServer(server.accept());   
  37.             mu.start();   
  38.         }   
  39.     }   
  40. }  

client code:

java 代码
  1. public class Client {   
  2.   
  3.     static Socket server;   
  4.   
  5.     public static void main(String[] args) throws Exception {   
  6.            
  7.         //set socket proxy.   
  8.         String proxyHost = "192.16.24.12";   
  9.         String proxyPort = "1080";   
  10.         System.getProperties().put("socksProxySet","true");   
  11.         System.getProperties().put("socksProxyHost",proxyHost);   
  12.         System.getProperties().put("socksProxyPort",proxyPort);    
  13.            
  14.         String host = "12.201.29.10";   
  15.         int port = 10086;   
  16.         if (args.length > 1)   
  17.         {   
  18.             host = args[0];   
  19.             port = Integer.parseInt(args[1]);   
  20.         }   
  21.         System.out.println("connetioning:" + host + ":" + port);   
  22.         server = new Socket(host, port);   
  23.         BufferedReader in = new BufferedReader(new InputStreamReader(server   
  24.                 .getInputStream()));   
  25.         PrintWriter out = new PrintWriter(server.getOutputStream());   
  26.         BufferedReader wt = new BufferedReader(new InputStreamReader(System.in));   
  27.         while (true) {   
  28.             String str = wt.readLine();   
  29.             out.println(str);   
  30.             out.flush();   
  31.             if (str.equals("end")) {   
  32.                 break;   
  33.             }   
  34.             System.out.println(in.readLine());   
  35.         }   
  36.         server.close();   
  37.     }   
  38. }  

 2.nio:非阻塞通讯模式

2.1NIO 设计背后的基石:反应器模式,用于事件多路分离和分派的体系结构模式。
反应器模式的核心功能如下:
将事件多路分用
将事件分派到各自相应的事件处理程序

NIO 的非阻塞 I/O 机制是围绕 选择器和 通道构建的。Channel 类表示服务器和客户机之间的一种通信机制。Selector 类是 Channel 的多路复用器。 Selector 类将传入客户机请求多路分用并将它们分派到各自的请求处理程序。
通道(Channel 类):表示服务器和客户机之间的一种通信机制。
选择器(Selector类):是 Channel 的多路复用器。

Selector 类将传入的客户机请求多路分用并将它们分派到各自的请求处理程序。简单的来说:NIO是一个基于事件的IO架构,最基本的思想就是:有事件我通知你,你再去做你的事情.而且NIO的主线程只有一个,不像传统的模型,需要多个线程以应对客户端请求,也减轻了JVM的工作量。
当Channel注册至Selector以后,经典的调用方法如下:
       nio中取得事件通知,就是在selector的select事件中完成的。在selector事件时有一个线程向操作系统询问,selector中注册的Channel&&SelectionKey的键值对的各种事件是否有发生,如果有则添加到selector的selectedKeys属性Set中去,并返回本次有多少个感兴趣的事情发生。如果发现这个值>0,表示有事件发生,马上迭代selectedKeys中的SelectionKey,
根据Key中的表示的事件,来做相应的处理。实际上,这段说明表明了异步socket的核心,即异步socket不过是将多个socket的调度(或者还有他们的线程调度)全部交给操作系统自己去完成,异步的核心Selector,不过是将这些调度收集、分发而已。

java 代码
  1. while (somecondition) {   
  2.     int n = selector.select(TIMEOUT);   
  3.     if (n == 0)   
  4.         continue;   
  5.     for (Iterator iter = selector.selectedKeys().iterator(); iter   
  6.             .hasNext();) {   
  7.         if (key.isAcceptable())   
  8.             doAcceptable(key);   
  9.         if (key.isConnectable())   
  10.             doConnectable(key);   
  11.         if (key.isValid() && key.isReadable())   
  12.             doReadable(key);   
  13.         if (key.isValid() && key.isWritable())   
  14.             doWritable(key);   
  15.         iter.remove();   
  16.     }   
  17. }  

 

2.2 nio example:
server code:

java 代码
  1. public class NonBlockingServer   
  2. {   
  3.     public Selector sel = null;   
  4.     public ServerSocketChannel server = null;   
  5.     public SocketChannel socket = null;   
  6.     public int port = 4900;   
  7.     String result = null;   
  8.   
  9.   
  10.     public NonBlockingServer()   
  11.     {   
  12.         System.out.println("Inside default ctor");   
  13.     }   
  14.        
  15.     public NonBlockingServer(int port)   
  16.     {   
  17.         System.out.println("Inside the other ctor");   
  18.         this.port = port;   
  19.     }   
  20.   
  21.     public void initializeOperations() throws IOException,UnknownHostException   
  22.     {   
  23.         System.out.println("Inside initialization");   
  24.         sel = Selector.open();   
  25.         server = ServerSocketChannel.open();   
  26.         server.configureBlocking(false);   
  27.         InetAddress ia = InetAddress.getLocalHost();   
  28.         InetSocketAddress isa = new InetSocketAddress(ia,port);   
  29.         server.socket().bind(isa);   
  30.     }   
  31.        
  32.     public void startServer() throws IOException   
  33.     {   
  34.         System.out.println("Inside startserver");   
  35.         initializeOperations();   
  36.         System.out.println("Abt to block on select()");   
  37.         SelectionKey acceptKey = server.register(sel, SelectionKey.OP_ACCEPT );    
  38.        
  39.         while (acceptKey.selector().select() > 0 )   
  40.         {      
  41.            
  42.             Set readyKeys = sel.selectedKeys();   
  43.             Iterator it = readyKeys.iterator();   
  44.   
  45.             while (it.hasNext()) {   
  46.                 SelectionKey key = (SelectionKey)it.next();   
  47.                 it.remove();   
  48.                    
  49.                 if (key.isAcceptable()) {   
  50.                     System.out.println("Key is Acceptable");   
  51.                     ServerSocketChannel ssc = (ServerSocketChannel) key.channel();   
  52.                     socket = (SocketChannel) ssc.accept();   
  53.                     socket.configureBlocking(false);   
  54.                     SelectionKey another = socket.register(sel,SelectionKey.OP_READ|SelectionKey.OP_WRITE);   
  55.                 }   
  56.                 if (key.isReadable()) {   
  57.                     System.out.println("Key is readable");   
  58.                     String ret = readMessage(key);   
  59.                     if (ret.length() > 0) {   
  60.                         writeMessage(socket,ret);   
  61.                     }   
  62.                 }   
  63.                 if (key.isWritable()) {   
  64.                     System.out.println("THe key is writable");   
  65.                     String ret = readMessage(key);   
  66.                     socket = (SocketChannel)key.channel();   
  67.                     if (result.length() > 0 ) {   
  68.                         writeMessage(socket,ret);   
  69.                     }   
  70.                 }   
  71.             }   
  72.         }   
  73.     }   
  74.   
  75.     public void writeMessage(SocketChannel socket,String ret)   
  76.     {   
  77.         System.out.println("Inside the loop");   
  78.   
  79.         if (ret.equals("quit") || ret.equals("shutdown")) {   
  80.             return;   
  81.         }   
  82.         try  
  83.         {   
  84.   
  85.             String s = "This is context from server!-----------------------------------------";   
  86.             Charset set = Charset.forName("us-ascii");   
  87.             CharsetDecoder dec = set.newDecoder();   
  88.             CharBuffer charBuf = dec.decode(ByteBuffer.wrap(s.getBytes()));   
  89.             System.out.println(charBuf.toString());   
  90.             int nBytes = socket.write(ByteBuffer.wrap((charBuf.toString()).getBytes()));   
  91.             System.out.println("nBytes = "+nBytes);   
  92.                 result = null;   
  93.         }   
  94.         catch(Exception e)   
  95.         {   
  96.             e.printStackTrace();   
  97.         }   
  98.   
  99.     }   
  100.      
  101.     public String readMessage(SelectionKey key)   
  102.     {   
  103.         int nBytes = 0;   
  104.         socket = (SocketChannel)key.channel();   
  105.         ByteBuffer buf = ByteBuffer.allocate(1024);   
  106.         try  
  107.         {   
  108.             nBytes = socket.read(buf);   
  109.             buf.flip();   
  110.             Charset charset = Charset.forName("us-ascii");   
  111.             CharsetDecoder decoder = charset.newDecoder();   
  112.             CharBuffer charBuffer = decoder.decode(buf);   
  113.             result = charBuffer.toString();   
  114.            
  115.         }   
  116.         catch(IOException e)   
  117.         {   
  118.             e.printStackTrace();   
  119.         }   
  120.         return result;   
  121.     }   
  122.   
  123.     public static void main(String args[])   
  124.     {   
  125.         NonBlockingServer nb;   
  126.         if (args.length < 1)   
  127.         {   
  128.             nb = new NonBlockingServer();   
  129.         }   
  130.         else  
  131.         {   
  132.             int port = Integer.parseInt(args[0]);   
  133.             nb = new NonBlockingServer(port);   
  134.         }   
  135.             
  136.         try  
  137.         {   
  138.             nb.startServer();   
  139.             System.out.println("the nonBlocking server is started!");   
  140.         }   
  141.         catch (IOException e)   
  142.         {   
  143.             e.printStackTrace();   
  144.             System.exit(-1);   
  145.         }   
  146.            
  147.     }   
  148. }  
client code:
  1. public class Client {   
  2.     public SocketChannel client = null;   
  3.   
  4.     public InetSocketAddress isa = null;   
  5.   
  6.     public RecvThread rt = null;   
  7.   
  8.     private String host;   
  9.   
  10.     private int port;   
  11.   
  12.     public Client(String host, int port) {   
  13.         this.host = host;   
  14.         this.port = port;   
  15.     }   
  16.   
  17.     public void makeConnection() {   
  18.         String proxyHost = "192.168.24.22";   
  19.         String proxyPort = "1080";   
  20.         System.getProperties().put("socksProxySet""true");   
  21.         System.getProperties().put("socksProxyHost", proxyHost);   
  22.         System.getProperties().put("socksProxyPort", proxyPort);   
  23.   
  24.         int result = 0;   
  25.         try {   
  26.             client = SocketChannel.open();   
  27.             isa = new InetSocketAddress(host, port);   
  28.             client.connect(isa);   
  29.             client.configureBlocking(false);   
  30.             receiveMessage();   
  31.         } catch (UnknownHostException e) {   
  32.             e.printStackTrace();   
  33.         } catch (IOException e) {   
  34.             e.printStackTrace();   
  35.         }   
  36.         long begin = System.currentTimeMillis();   
  37.   
  38.         sendMessage();   
  39.   
  40.         long end = System.currentTimeMillis();   
  41.         long userTime = end - begin;   
  42.         System.out.println("use tiem: " + userTime);   
  43.         try {   
  44.             interruptThread();   
  45.             client.close();   
  46.             System.exit(0);   
  47.         } catch (IOException e) {   
  48.             e.printStackTrace();   
  49.         }   
  50.     }   
  51.   
  52.     public int sendMessage() {   
  53.                 System.out.println("Inside SendMessage");   
  54.         String msg = null;   
  55.         ByteBuffer bytebuf;   
  56.         int nBytes = 0;   
  57.         try {   
  58.             msg = "It's message from client!";   
  59.             System.out.println("msg is "+msg);   
  60.             bytebuf = ByteBuffer.wrap(msg.getBytes());   
  61.             for (int i = 0; i < 1000; i++) {   
  62.                 nBytes = client.write(bytebuf);   
  63.                 System.out.println(i + " finished");   
  64.             }   
  65.             interruptThread();   
  66.             try {   
  67.                 Thread.sleep(5000);   
  68.             } catch (Exception e) {   
  69.                 e.printStackTrace();   
  70.             }   
  71.             client.close();   
  72.             return -1;   
  73.   
  74.         } catch (IOException e) {   
  75.             e.printStackTrace();   
  76.         }   
  77.   
  78.         return nBytes;   
  79.   
  80.     }   
  81.   
  82.     public void receiveMessage() {   
  83.         rt = new RecvThread("Receive THread", client);   
  84.         rt.start();   
  85.   
  86.     }   
  87.   
  88.     public void interruptThread() {   
  89.         rt.val = false;   
  90.     }   
  91.   
  92.     public static void main(String args[]) {   
  93.         if (args.length < 2) {   
  94.             System.err.println("You should put 2 args: host,port");   
  95.         } else {   
  96.             String host = args[0];   
  97.             int port = Integer.parseInt(args[1]);   
  98.             Client cl = new Client(host, port);   
  99.             cl.makeConnection();   
  100.         }   
  101.         BufferedReader in = new BufferedReader(new InputStreamReader(System.in));   
  102.         String msg;   
  103.   
  104.     }   
  105.   
  106.     public class RecvThread extends Thread {   
  107.         public SocketChannel sc = null;   
  108.   
  109.         public boolean val = true;   
  110.   
  111.         public RecvThread(String str, SocketChannel client) {   
  112.             super(str);   
  113.             sc = client;   
  114.         }   
  115.   
  116.         public void run() {   
  117.             int nBytes = 0;   
  118.             ByteBuffer buf = ByteBuffer.allocate(2048);   
  119.             try {   
  120.                 while (val) {   
  121.                     while ((nBytes = nBytes = client.read(buf)) > 0) {   
  122.                         buf.flip();   
  123.                         Charset charset = Charset.forName("us-ascii");   
  124.                         CharsetDecoder decoder = charset.newDecoder();   
  125.                         CharBuffer charBuffer = decoder.decode(buf);   
  126.                         String result = charBuffer.toString();   
  127.                         System.out.println("the server return: " + result);   
  128.                         buf.flip();   
  129.   
  130.                     }   
  131.                 }   
  132.   
  133.             } catch (IOException e) {   
  134.                 e.printStackTrace();   
  135.   
  136.             } </span
 
原创粉丝点击