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

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

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

  經過上面步驟後該ServerSocketChannel可以接受客戶端的連接請求但我們需要調用Selector的select()方法來監聽所有Channel上的IO操作

  程序清單codes///NoBlock/NServerjava

  public class NServer

  {

  //用於檢測所有Channel狀態的Selector

  private Selector selector = null;

  //定義實現編碼解碼的字符集對象

  private Charset charset = CharsetforName(UTF

  public void init()throws IOException

  {

  selector = Selectoropen()

  //通過open方法來打開一個未綁定的ServerSocketChannel實例

  ServerSocketChannel server = ServerSocketChannelopen()

  InetSocketAddress isa = new InetSocketAddress(

  

  //將該ServerSocketChannel綁定到指定IP地址

  serversocket()bind(isa)

  //設置ServerSocket以非阻塞方式工作

  serverconfigureBlocking(false)

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

  serverregister(selector SelectionKeyOP_ACCEPT)

  while (selectorselect() >

  {

  //依次處理selector上的每個已選擇的SelectionKey

  for (SelectionKey sk : selectorselectedKeys())

  {

  //從selector上的已選擇Key集中刪除正在處理的SelectionKey

  selectorselectedKeys()remove(sk)                             //①

  //如果sk對應的通道包含客戶端的連接請求

  if (skisAcceptable())                                             //②

  {

  //調用accept方法接受連接產生服務器端對應的SocketChannel

  SocketChannel sc = serveraccept()

  //設置采用非阻塞模式

  scconfigureBlocking(false)

  //將該SocketChannel也注冊到selector

  scregister(selector SelectionKeyOP_READ)

  //將sk對應的Channel設置成准備接受其他請求

  skinterestOps(SelectionKeyOP_ACCEPT)

  }

  //如果sk對應的通道有數據需要讀取

  if (skisReadable())                                               //③

  {

  //獲取該SelectionKey對應的Channel該Channel中有可讀的數據

  SocketChannel sc = (SocketChannel)skchannel()

  //定義准備執行讀取數據的ByteBuffer

  ByteBuffer buff = ByteBufferallocate(

  String content = ;

  //開始讀取數據

  try

  {

  while(scread(buff) >

  {

  buffflip()

  content += charsetdecode(buff)

  }

  //打印從該sk對應的Channel裡讀取到的數據

  Systemoutprintln(===== + content)

  //將sk對應的Channel設置成准備下一次讀取

  skinterestOps(SelectionKeyOP_READ)

  }

  //如果捕捉到該sk對應的Channel出現了異常即表明該Channel

  //對應的Client出現了問題所以從Selector中取消sk的注冊

  catch (IOException ex)

  {

  //從Selector中刪除指定的SelectionKey

  skcancel()

  if (skchannel() != null)

  {

  skchannel()close()

  }

  }

  //如果content的長度大於即聊天信息不為空

  if (contentlength() >

  {

  //遍歷該selector裡注冊的所有SelectKey

  for (SelectionKey key : selectorkeys())

  {

  //獲取該key對應的Channel

  Channel targetChannel = keychannel()

  //如果該channel是SocketChannel對象

  if (targetChannel instanceof SocketChannel)

  {

  //將讀到的內容寫入該Channel中

  SocketChannel dest = (SocketChannel)targetChannel;

  destwrite(charsetencode(content))

  }

  }

  }

  }

  }

  }

  }

  public static void main(String[] args)

  throws IOException

  {

  new NServer()init()

  }

  }

  上面程序啟動時即建立一個可監聽連接請求的ServerSocketChannel並將該Channel注冊到指定Selector接著程序直接采用循環不斷監控Selector對象的select()方法返回值當該返回值大於時處理該Selector上所有被選擇的SelectionKey

  開始處理指定SelectionKey之後立即從該Selector中的被選擇的SelectionKey集合中刪除該SelectionKey如程序中①號代碼所示

[]  []  


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