小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

用java.nio.*進(jìn)行網(wǎng)絡(luò)編程(轉(zhuǎn)載),主要是基礎(chǔ)應(yīng)用,異步通信

 雨憶 2007-12-07
用java.nio.*進(jìn)行網(wǎng)絡(luò)編程
作者:網(wǎng)管整理   來源:bitsCN.com   PV: 1000
 
前言
    因為打算用java編寫異步通信的server和client程序,筆者便學(xué)習(xí)使用java.nio
開發(fā)包,其間遇到一些問題,上網(wǎng)卻發(fā)現(xiàn)網(wǎng)上對它的應(yīng)用描述的不是很多。所以,筆者不惜班門弄斧,做些簡單的討論,以便大家更進(jìn)一步的討論。

 

對相關(guān)類的簡單介紹
    java.nio.*, 據(jù)說它提供了一些更加底層的一些功能,如:類似windows環(huán)境下的
AsyncSocket類的異步操作的功能,能顯著降低server端程序的線程管理開銷。
    因為大多數(shù)應(yīng)用是建立在TCP之上,所以在此只說說SocketChannel,
ServerSocketChannel,Selector和ByteBuffer這幾個類.前三個最終都源自channel類。而channel 類,可以理解為在具體I/O或文件對象之上抽象的一個操作對象,我們通過操作channel的讀寫達(dá)到對其對應(yīng)的文件或I/O對象(包括socket)讀寫的目的。讀寫的內(nèi)容在內(nèi)存中放在ByteBuffer類提供的緩沖區(qū)??偠灾?,channel作為一個橋梁,連接了I/O對象和內(nèi)存中的ByteBuffer,實現(xiàn)了I/O的更高效的存取。
    一個基于TCP的服務(wù)器端程序,必然有個偵聽端和若干個通信端,它們在nio中由對應(yīng)的ServerSocketChannel 和SocketChannel類來實現(xiàn)。為了達(dá)到異步I/O操作的目的,需要Selector類,它能檢測到I/O對象的狀態(tài)。 中國.網(wǎng)管聯(lián)盟

    SocketChannel類是抽象類,通過調(diào)用它的靜態(tài)函數(shù)open(),可生成一個
SocketChannel對象,該對象對應(yīng)一個java.net.Socket,可通過SocketChannel.socket()獲得,而其對應(yīng)的Socket也可通過調(diào)用函數(shù)getChannel()得到已建立的相應(yīng)SocketChannel。
    SocketChannel與它的socket是一一對應(yīng)的。SocketChannel的操作與Socket也很相似. DL.bitsCN.com網(wǎng)管軟件下載

    ServerSocketChannel也是通過調(diào)用它的靜態(tài)函數(shù)open()生成的,只是它不能
直接調(diào)用bind()函數(shù)來綁定一個地址,需要它對應(yīng)的ServerSocket來完成綁定工作,一般可按如下步驟做:
    ServerSocketChannel ssc = new ServerSocketChannel.open();
    ssc.socket().bind(InetSocketAddress(host,port));

 

    羅嗦了半天,還是看看最簡單的C/S實現(xiàn)吧,服務(wù)器提供了基本的回射(echo)功
能,其中提供了較詳細(xì)的注釋。

 

源碼分析

中國網(wǎng)管論壇

 

1.服務(wù)器端:
////////////////////////
//AsyncServer.java
//   by zztudou@163.com
////////////////////////
import java.nio.channels.SocketChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel;
import java.nio.channels.spi.SelectorProvider;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Iterator;
import java.util.LinkedList;
import java.io.IOException; bitsCN.Com

class AsyncServer implements Runnable{ 
 private ByteBuffer r_buff = ByteBuffer.allocate(1024);
 private ByteBuffer w_buff = ByteBuffer.allocate(1024);
 private static int port = 8848;
 
 public AsyncServer(){
  new Thread(this).start();
 }
 
 public void run(){    
  try{
   //生成一個偵聽端
   ServerSocketChannel ssc = ServerSocketChannel.open();
   //將偵聽端設(shè)為異步方式
   ssc.configureBlocking(false);
   //生成一個信號監(jiān)視器
   Selector s = Selector.open();
   //偵聽端綁定到一個端口
   ssc.socket().bind(new InetSocketAddress(port));
   //設(shè)置偵聽端所選的異步信號OP_ACCEPT
   ssc.register(s,SelectionKey.OP_ACCEPT);
   
   System.out.println("echo server has been set up ......");

 
   while(true){
    int n = s.select();
    if (n == 0) {//沒有指定的I/O事件發(fā)生
     continue;
    }     
    Iterator it = s.selectedKeys().iterator();     
    while (it.hasNext()) {
     SelectionKey key = (SelectionKey) it.next();
     if (key.isAcceptable()) {//偵聽端信號觸發(fā)
      ServerSocketChannel server = (ServerSocketChannel) key.channel();
      //接受一個新的連接
      SocketChannel sc = server.accept();
      sc.configureBlocking(false);
      //設(shè)置該socket的異步信號OP_READ:當(dāng)socket可讀時, BBS.bitsCN.com網(wǎng)管論壇

 

     //觸發(fā)函數(shù)DealwithData();
      sc.register(s,SelectionKey.OP_READ);
     }   
     if (key.isReadable()) {//某socket可讀信號
      DealwithData(key);
     }     
     it.remove();
    }
   }
  }
  catch(Exception e){
   e.printStackTrace(); 
  }
 }
  
 public void DealwithData(SelectionKey key) throws IOException{
  int count;
  //由key獲取指定socketchannel的引用
  SocketChannel sc = (SocketChannel)key.channel();
  r_buff.clear();
  //讀取數(shù)據(jù)到r_buff
  while((count = sc.read(r_buff))> 0)
   ; bitsCN.Com
  //確保r_buff可讀
  r_buff.flip();
  
  w_buff.clear();
  //將r_buff內(nèi)容拷入w_buff  
  w_buff.put(r_buff);
  w_buff.flip();
  //將數(shù)據(jù)返回給客戶端
  EchoToClient(sc);
 
  w_buff.clear();
  r_buff.clear();
 }
 
 public void EchoToClient(SocketChannel sc) throws IOException{
  while(w_buff.hasRemaining())
   sc.write(w_buff);
 }
 
 public static void main(String args[]){
  if(args.length > 0){
   port = Integer.parseInt(args[0]);
  }
  new AsyncServer();
 }
}
在當(dāng)前目錄下運行:
    javac AsynServer.java
后,若無編譯出錯,接下來可運行:
    java AsynServer  或 java AsynServer ×××(端口號)
上述服務(wù)程序在運行時,可指定其偵聽端口,否則程序會取8848為默認(rèn)端口。
 
2.客戶端的簡單示例:
////////////////////////
//AsyncClient.java
//   by zztudou@163.com
////////////////////////
import java.nio.channels.SocketChannel;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Selector;
import java.nio.channels.SelectionKey;
中國網(wǎng)管聯(lián)盟

 

import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader; DL.bitsCN.com網(wǎng)管軟件下載

class AsyncClient{
 private SocketChannel sc;
 private final int MAX_LENGTH = 1024;
 private ByteBuffer r_buff = ByteBuffer.allocate(MAX_LENGTH);
 private ByteBuffer w_buff = ByteBuffer.allocate(MAX_LENGTH);
 private static String host ;
 private static int port = 8848;
 
 public AsyncClient(){
  try {
   InetSocketAddress addr = new InetSocketAddress(host,port);
   //生成一個socketchannel
   sc = SocketChannel.open();
         
   //連接到server
   sc.connect(addr);
   while(!sc.finishConnect())
    ;  
   System.out.println("connection has been established!...");
    
   while(true){
    //回射消息
    String echo; 

    try{
     System.err.println("Enter msg you'd like to send:  ");
     BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
     //輸入回射消息
     echo = br.readLine();
     
     //把回射消息放入w_buff中    
     w_buff.clear();
     w_buff.put(echo.getBytes());
     w_buff.flip();
    }catch(IOException ioe){
     System.err.println("sth. is wrong with br.readline() ");
    }    
  
    //發(fā)送消息
    while(w_buff.hasRemaining())
     sc.write(w_buff);
    w_buff.clear();
    
    //進(jìn)入接收狀態(tài)
    Rec();
    //間隔1秒
    Thread.currentThread().sleep(1000);
   }  
  }catch(IOException ioe){
   ioe.printStackTrace();
  }
  catch(InterruptedException ie){
   ie.printStackTrace();
  }  
 }
////////////
 //讀取server端發(fā)回的數(shù)據(jù),并顯示
 public void Rec() throws IOException{
  int count;
  r_buff.clear(); 
  count=sc.read(r_buff);
  r_buff.flip();  
  byte[] temp = new byte[r_buff.limit()];
  r_buff.get(temp);
  System.out.println("reply is " + count +" long, and content is: " + new String(temp));
 }
 
 public static void main(String args[]){
  if(args.length < 1){//輸入需有主機名或IP地址
   try{
    System.err.println("Enter host name: ");
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    host = br.readLine();
   }catch(IOException ioe){
    System.err.println("sth. is wrong with br.readline() ");
   }
  }
  else if(args.length == 1){
   host = args[0];
  }
  else if(args.length > 1){
   host = args[0];
   port = Integer.parseInt(args[1]);
  }

 

  new AsyncClient();
 }
}

在當(dāng)前目錄下運行:
  javac AsynClient.java
后,若無編譯出錯,確認(rèn)AsyncServer已經(jīng)運行的情況下,接下來可運行:
  java AsynClient hostname 或 java AsynClient hostname ×××(端口號)
并按提示進(jìn)行操作即可。 中國網(wǎng)管論壇

總結(jié)
    總的來說,用nio進(jìn)行網(wǎng)絡(luò)編程還是很有新意的,服務(wù)器端軟件能在一個線程中維護(hù)與眾多客戶端的通信連接。筆者在本文中試圖用一個典型的回射例子說明如何用nio建立最基本的C/S應(yīng)用。希望大家能試著用用它。
    另外,筆者在實踐中也發(fā)現(xiàn)nio在應(yīng)用中存在的一些難題,比如如何應(yīng)用SocketChannel的繼承類,以及如何在socketchannel之上應(yīng)用SSL(Secure Socket Layer)等等,因而希望這篇文章只是拋磚引玉,引起大家對nio作進(jìn)一步的討論。 bbs.bitsCN.com

在當(dāng)前目錄下運行:
    javac AsynServer.java
后,若無編譯出錯,接下來可運行:
    java AsynServer  或 java AsynServer ×××(端口號)
上述服務(wù)程序在運行時,可指定其偵聽端口,否則程序會取8848為默認(rèn)端口。   bbs.bitsCN.com

2.客戶端的簡單示例:
////////////////////////
//AsyncClient.java
//   by zztudou@163.com
////////////////////////
import java.nio.channels.SocketChannel;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Selector;
import java.nio.channels.SelectionKey; DL.bitsCN.com網(wǎng)管軟件下載

import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;

class AsyncClient{
 private SocketChannel sc;
 private final int MAX_LENGTH = 1024;
 private ByteBuffer r_buff = ByteBuffer.allocate(MAX_LENGTH);
 private ByteBuffer w_buff = ByteBuffer.allocate(MAX_LENGTH);
 private static String host ;
 private static int port = 8848;
 
 public AsyncClient(){
  try {
   InetSocketAddress addr = new InetSocketAddress(host,port);
   //生成一個socketchannel
   sc = SocketChannel.open();
         
   //連接到server
   sc.connect(addr);
   while(!sc.finishConnect())
    ;  
   System.out.println("connection has been established!...");
    
   while(true){
    //回射消息
    String echo; bitsCN.Com
    try{
     System.err.println("Enter msg you'd like to send:  ");
     BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
     //輸入回射消息
     echo = br.readLine();
     
     //把回射消息放入w_buff中    
     w_buff.clear();
     w_buff.put(echo.getBytes());
     w_buff.flip();
    }catch(IOException ioe){
     System.err.println("sth. is wrong with br.readline() ");
    }    
  
    //發(fā)送消息
    while(w_buff.hasRemaining())
     sc.write(w_buff);
    w_buff.clear();     BBS.bitsCN.com網(wǎng)管論壇
    
    //進(jìn)入接收狀態(tài)
    Rec();
    //間隔1秒
    Thread.currentThread().sleep(1000);
   }  
  }catch(IOException ioe){
   ioe.printStackTrace();
  }
  catch(InterruptedException ie){
   ie.printStackTrace();
  }  
 }
 
 ////////////
 // 讀取server端發(fā)回的數(shù)據(jù),并顯示
 public void Rec() throws IOException{
  int count;
  r_buff.clear(); 
  while((count=sc.read(r_buff))>0)
   ;
  r_buff.flip();  
  byte[] temp = new byte[r_buff.limit()];
  System.out.println("reply is : " + new String(temp));
 }
 
 public static void main(String args[]){


  if(args.length < 1){//輸入需有主機名或IP地址
   try{
    System.err.println("Enter host name: ");
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    host = br.readLine();
   }catch(IOException ioe){
    System.err.println("sth. is wrong with br.readline() ");
   }
  }
  else if(args.length == 1){
   host = args[0];
  }
  else if(args.length > 1){
   host = args[0];
   port = Integer.parseInt(args[1]);
  }

 

  new AsyncClient();
 }
}

 

在當(dāng)前目錄下運行:
   javac AsynClient.java
后,若無編譯出錯,確認(rèn)AsyncServer已經(jīng)運行的情況下,接下來可運行:
   java AsynClient hostname 或 java AsynClient hostname ×××(端口號)
并按提示進(jìn)行操作即可。 bitsCN.nET中國網(wǎng)管博客

總結(jié)
    總的來說,用nio進(jìn)行網(wǎng)絡(luò)編程還是很有新意的,服務(wù)器端軟件能在一個線程中維護(hù)與眾多客戶端的通信連接。筆者在本文中試圖用一個典型的回射例子說明如何用nio建立最基本的C/S應(yīng)用。希望大家能試著用用它。
    另外,筆者在實踐中也發(fā)現(xiàn)nio在應(yīng)用中存在的一些難題,比如如何應(yīng)用SocketChannel的繼承類,以及如何在socketchannel之上應(yīng)用SSL(Secure Socket Layer)等等,因而希望這篇文章只是拋磚引玉,引起大家對nio作進(jìn)一步的討論。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多