熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

瘋狂Java講義:使用NIO實現非阻塞Socket通信(2)[2]

2022-06-13   來源: Java核心技術 

  服務器端的Selector僅需要監聽兩種操作連接和讀數據所以程序中分別處理了這兩種操作如程序中②和③代碼所示處理連接操作之時系統只需將接受連接後產生的SocketChannel注冊到指定Selector對象即可處理讀數據操作之時系統先從該Socket中讀取數據再將數據寫入Selector上注冊的所有Channel

  使用NIO來實現服務器時甚至無須使用ArrayList來保存服務器中所有SocketChannel因為所有的SocketChannel都需要注冊到指定的Selector對象除此之外當客戶端關閉時會導致服務器對應的Channel也拋出異常而且本程序只有一條線程如果該異常得不到處理將會導致整個服務器退出所以程序捕捉了這種異常並在處理異常時從Selector刪除異常Channel的注冊如程序中斜體字代碼所示

  本示例程序的客戶端程序需要兩個線程一個線程負責讀取用戶的鍵盤輸入並將輸入的內容寫入SocketChannel中另一個線程則不斷地查詢Selector對象的select()方法的返回值

  程序清單codes///NoBlock/NClientjava

  public class NClient

  {

  //定義檢測SocketChannel的Selector對象

  private Selector selector = null;

  //定義處理編碼和解碼的字符集

  private Charset charset = CharsetforName(UTF

  //客戶端SocketChannel

  private SocketChannel sc = null;

  public void init()throws IOException

  {

  selector = Selectoropen()

  InetSocketAddress isa = new InetSocketAddress(

  //調用open靜態方法創建連接到指定主機的SocketChannel

  sc = SocketChannelopen(isa)

  //設置該sc以非阻塞方式工作

  scconfigureBlocking(false)

  //將SocketChannel對象注冊到指定Selector

  scregister(selector SelectionKeyOP_READ)

  //啟動讀取服務器端數據的線程

  new ClientThread()start()

  //創建鍵盤輸入流

  Scanner scan = new Scanner(Systemin)

  while (scanhasNextLine())

  {

  //讀取鍵盤輸入

  String line = scannextLine()

  //將鍵盤輸入的內容輸出到SocketChannel中

  scwrite(charsetencode(line))

  }

  }

  //定義讀取服務器數據的線程

  private class ClientThread extends Thread

  {

  public void run()

  {

  try

  {

  while (selectorselect() >

  {

  //遍歷每個有可用IO操作Channel對應的SelectionKey

  for (SelectionKey sk : selectorselectedKeys())

  {

  //刪除正在處理的SelectionKey

  selectorselectedKeys()remove(sk)

  //如果該SelectionKey對應的Channel中有可讀的數據

  if (skisReadable())

  {

  //使用NIO讀取Channel中的數據

  SocketChannel sc = (SocketChannel)skchannel()

  ByteBuffer buff = ByteBufferallocate(

  String content = ;

  while(scread(buff) >

  {

  scread(buff)

  buffflip()

  content += charsetdecode(buff)

  }

  //打印輸出讀取的內容

  Systemoutprintln(聊天信息 + content)

  //為下一次讀取作准備

  skinterestOps(SelectionKeyOP_READ)

  }

  }

  }

  }

  catch (IOException ex)

  {

  exprintStackTrace()

  }

  }

  }

  public static void main(String[] args)

  throws IOException

  {

  new NClient()init()

  }

  }

  相比之下客戶端程序比服務器程序要簡單多了客戶端只有一條SocketChannel將該SocketChannel注冊到指定Selector後程序啟動另一條線程來監測該Selector即可

       返回目錄瘋狂Java講義

       編輯推薦

       Java程序性能優化讓你的Java程序更快更穩定

       新手學Java 編程

       Java程序設計培訓視頻教程

[]  []  


From:http://tw.wingwit.com/Article/program/Java/hx/201311/27262.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.