1. gzyueqian
      18529173453
      首頁 > 新聞中心 > > 正文

      使用Java NIO提高服務端程序的性能

      更新時間: 2007-06-04 09:47:26來源: 粵嵌教育瀏覽量:786


        結合具體的Java Socket編程,討論使用NIO提高服務端程序的性能的問題。

        Java NIO增加了新的SocketChannel、ServerSocketChannel等類來提供對構建高性能的服務端程序的支持。 SocketChannel、ServerSocketChannel能夠在非阻塞的模式下工作,它們都是selectable的類。在構建服務器或者中間件時,推薦使用Java NIO。

        在傳統的網絡編程中,我們通常使用一個專用線程(Thread)來處理一個Socket連接,通過使用NIO,一個或者很少幾個Socket線程就可以處理成千上萬個活動的Socket連接。

        通常情況下,通過ServerSocketChannel.open()獲得一個ServerSocketChannel的實例,通過SocketChannel.open或者serverSocketChannel.accept()獲得一個SocketChannel實例。要使ServerSocketChannel或者SocketChannel在非阻塞的模式下操作,可以調用

      serverSocketChannel.configureBlocking (false);

      或者

      socketChannel.configureBlocking (false);

      語句來達到目的。通常情況下,服務端可以使用非阻塞的ServerSocketChannel,這樣,服務端的程序就可以更容易地同時處理多個socket線程。

        下面我們來看一個綜合例子,這個例子使用了ServerSocketChannel、SocketChannel開發了一個非阻塞的、能處理多線程的Echo服務端程序,見示例12-14。

      【程序源代碼】

      1 // ==================== Program Discription =====================
      2 // 程序名稱:示例12-14 : SocketChannelDemo.java
      3 // 程序目的:學習Java NIO#SocketChannel
      4 // ==============================================================
      5
      6
      7 import java.nio.ByteBuffer;
      8 import java.nio.channels.ServerSocketChannel;
      9 import java.nio.channels.SocketChannel;
      10 import java.nio.channels.Selector;
      11 import java.nio.channels.SelectionKey;
      12 import java.nio.channels.SelectableChannel;
      13
      14 import java.net.Socket;
      15 import java.net.ServerSocket;
      16 import java.net.InetSocketAddress;
      17 import java.util.Iterator;
      18
      19 public class SocketChannelDemo

      20
      21 {
      22 public static int PORT_NUMBER = 23;//監聽端口
      23 ServerSocketChannel serverChannel;
      24 ServerSocket serverSocket ;
      25 Selector selector ;
      26 private ByteBuffer buffer = ByteBuffer.allocateDirect (1024);
      27
      28 public static void main (String [] args)
      29 throws Exception
      30 {
      31 SocketChannelDemo server=new SocketChannelDemo();
      32 server.init(args);
      33 server.startWork();
      34 }
      35
      36
      37 public void init (String [] argv)throws Exception
      38 {
      39 int port = PORT_NUMBER;
      40
      41 if (argv.length > 0) {
      42 port = Integer.parseInt (argv [0]);
      43 }
      44
      45 System.out.println ("Listening on port " + port);
      46
      47 // 分配一個ServerSocketChannel
      48 serverChannel = ServerSocketChannel.open();
      49 // 從ServerSocketChannel里獲得一個對應的Socket
      50 serverSocket = serverChannel.socket();
      51 // 生成一個Selector
      52 selector = Selector.open();
      53
      54 // 把Socket綁定到端口上
      55 serverSocket.bind (new InetSocketAddress (port));
      56 //serverChannel為非bolck
      57 serverChannel.configureBlocking (false);
      58
      59 // 通過Selector注冊ServerSocetChannel
      60 serverChannel.register (selector, SelectionKey.OP_ACCEPT);
      61
      62 }
      63
      64 public void startWork()throws Exception

      65
      66 {
      67 while (true) {
      68
      69 int n = selector.select();//獲得IO準備就緒的channel數量
      70
      71 if (n == 0) {
      72 continue; // 沒有channel準備就緒,繼續執行
      73 }
      74
      75 // 用一個iterator返回Selector的selectedkeys
      76 Iterator it = selector.selectedKeys().iterator();
      77
      78 // 處理每一個SelectionKey
      79 while (it.hasNext()) {
      80 SelectionKey key = (SelectionKey) it.next();
      81
      82 // 判斷是否有新的連接到達
      83 if (key.isAcceptable()) {
      84           //返回SelectionKey的ServerSocketChannel
      85 ServerSocketChannel server =
      (ServerSocketChannel) key.channel();
      86 SocketChannel channel = server.accept();
      87
      88 registerChannel (selector, channel,
      89 SelectionKey.OP_READ);
      90
      91 doWork (channel);
      92 }
      93
      94 // 判斷是否有數據在此channel里需要讀取
      95 if (key.isReadable()) {
      96
      97 processData (key);
      98
      99 }
      100
      101 //刪除 selectedkeys
      102 it.remove();
      103 }
      104 }
      105 }
      106 protected void registerChannel (Selector selector,
      107 SelectableChannel channel, int ops)
      108 throws Exception
      109 {

      110 if (channel == null) {
      111 return;
      112 }
      113
      114
      115 channel.configureBlocking (false);
      116
      117 channel.register (selector, ops);
      118 }
      119
      120 //處理接收的數據
      121 protected void processData (SelectionKey key)
      122 throws Exception
      123 {
      124
      125
      126 SocketChannel socketChannel = (SocketChannel) key.channel();
      127 int count;
      128
      129 buffer.clear(); // 清空buffer
      130
      131 // 讀取所有的數據
      132 while ((count = socketChannel.read (buffer)) > 0) {
      133 buffer.flip();
      134
      135 // send the data, don′t assume it goes all at once
      136 while (buffer.hasRemaining())
      137 {
      138 //如果收到回車鍵,則在返回的字符前增加[echo]$字樣
      139 if(buffer.get()==(char)13)
      140 {
      141 buffer.clear();
      142 buffer.put("[echo]___FCKpd___0quot;.getBytes());
      143 buffer.flip();
      144
      145 }
      146 socketChannel.write (buffer);//在Socket里寫數據
      147 }
      148
      149 buffer.clear(); // 清空buffer
      150 }
      151
      152 if (count < 0) {
      153 // count<0,說明已經讀取完畢
      154 socketChannel.close();

      155 }
      156 }
      157
      158
      159 private void doWork (SocketChannel channel)throws Exception
      160 {
      161 buffer.clear();
      162 buffer.put ("
      Hello,I am working,please input some thing,and i will echo to you!
      [echo]
      ___FCKpd___0quot;.getBytes());
      163 buffer.flip();
      164 channel.write (buffer);
      165 }
      166
      167 }

      使用:運行此程序,然后在控制臺輸入命令telnet localhost 23。

      免費預約試聽課

      亚洲另类欧美综合久久图片区_亚洲中文字幕日产无码2020_欧美日本一区二区三区桃色视频_亚洲AⅤ天堂一区二区三区

      
      

      1. 一级一黄免费视频在线看 | 中文字幕日本一区久久 | 亚洲国产精品久久精品怡红院 | 亚洲色天堂在线电影 | 人伊香蕉久久精品 | 亚洲Av不卡在线 |