程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java運用NIO包完成Socket通訊的實例代碼

Java運用NIO包完成Socket通訊的實例代碼

編輯:關於JAVA

Java運用NIO包完成Socket通訊的實例代碼。本站提示廣大學習愛好者:(Java運用NIO包完成Socket通訊的實例代碼)文章只能為提供參考,不一定能成為您想要的結果。以下是Java運用NIO包完成Socket通訊的實例代碼正文


後面幾篇文章引見了運用java.io和java.net類庫完成的Socket通訊,上面引見一下運用java.nio類庫完成的Socket。

java.nio包是Java在1.4之後添加的,用來進步I/O操作的效率。在nio包中次要包括以下幾個類或接口:

 Buffer:緩沖區,用降臨時寄存輸出或輸入數據。  Charset:用來把Unicode字符編碼和其它字符編碼互轉。  Channel:數據傳輸通道,用來把Buffer中的數據寫入到數據源,或許把數據源中的數據讀入到Buffer。  Selector:用來支持異步I/O操作,也叫非阻塞I/O操作。

nio包中次要經過上面兩個方面來進步I/O操作效率:

 經過Buffer和Channel來進步I/O操作的速度。  經過Selector來支持非阻塞I/O操作。

上面來看一下順序中是怎樣經過這些類庫完成Socket功用。

首先引見一下幾個輔佐類

輔佐類SerializableUtil,這個類用來把java對象序列化成字節數組,或許把字節數組反序列化成java對象。

package com.googlecode.garbagecan.test.socket; 
 
import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
 
public class SerializableUtil { 
   
  public static byte[] toBytes(Object object) { 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    ObjectOutputStream oos = null; 
    try { 
      oos = new ObjectOutputStream(baos); 
      oos.writeObject(object); 
      byte[] bytes = baos.toByteArray(); 
      return bytes; 
    } catch(IOException ex) { 
      throw new RuntimeException(ex.getMessage(), ex); 
    } finally { 
      try { 
        oos.close(); 
      } catch (Exception e) {} 
    } 
  } 
   
  public static Object toObject(byte[] bytes) { 
    ByteArrayInputStream bais = new ByteArrayInputStream(bytes); 
    ObjectInputStream ois = null; 
    try { 
      ois = new ObjectInputStream(bais); 
      Object object = ois.readObject(); 
      return object; 
    } catch(IOException ex) { 
      throw new RuntimeException(ex.getMessage(), ex); 
    } catch(ClassNotFoundException ex) { 
      throw new RuntimeException(ex.getMessage(), ex); 
    } finally { 
      try { 
        ois.close(); 
      } catch (Exception e) {} 
    } 
  } 
} 

輔佐類MyRequestObject和MyResponseObject,這兩個類是普通的java對象,完成了Serializable接口。MyRequestObject類是Client收回的懇求,MyResponseObject是Server端作出的呼應。

package com.googlecode.garbagecan.test.socket.nio; 
 
import java.io.Serializable; 
 
public class MyRequestObject implements Serializable { 
 
  private static final long serialVersionUID = 1L; 
 
  private String name; 
   
  private String value; 
 
  private byte[] bytes; 
   
  public MyRequestObject(String name, String value) { 
    this.name = name; 
    this.value = value; 
    this.bytes = new byte[1024]; 
  } 
   
  public String getName() { 
    return name; 
  } 
 
  public void setName(String name) { 
    this.name = name; 
  } 
 
  public String getValue() { 
    return value; 
  } 
 
  public void setValue(String value) { 
    this.value = value; 
  } 
   
  @Override 
  public String toString() { 
    StringBuffer sb = new StringBuffer(); 
    sb.append("Request [name: " + name + ", value: " + value + ", bytes: " + bytes.length+ "]"); 
    return sb.toString(); 
  } 
} 
 
package com.googlecode.garbagecan.test.socket.nio; 
 
import java.io.Serializable; 
 
public class MyResponseObject implements Serializable { 
 
  private static final long serialVersionUID = 1L; 
 
  private String name; 
   
  private String value; 
 
  private byte[] bytes; 
   
  public MyResponseObject(String name, String value) { 
    this.name = name; 
    this.value = value; 
    this.bytes = new byte[1024]; 
  } 
   
  public String getName() { 
    return name; 
  } 
 
  public void setName(String name) { 
    this.name = name; 
  } 
 
  public String getValue() { 
    return value; 
  } 
 
  public void setValue(String value) { 
    this.value = value; 
  } 
   
  @Override 
  public String toString() { 
    StringBuffer sb = new StringBuffer(); 
    sb.append("Response [name: " + name + ", value: " + value + ", bytes: " + bytes.length+ "]"); 
    return sb.toString(); 
  } 
} 

上面次要看一下Server端的代碼,其中有一些英文正文對了解代碼很有協助,正文次要是來源jdk的文檔和例子,這裡就沒有再翻譯

package com.googlecode.garbagecan.test.socket.nio; 
 
import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import java.net.InetSocketAddress; 
import java.nio.ByteBuffer; 
import java.nio.channels.ClosedChannelException; 
import java.nio.channels.SelectionKey; 
import java.nio.channels.Selector; 
import java.nio.channels.ServerSocketChannel; 
import java.nio.channels.SocketChannel; 
import java.util.Iterator; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
 
import com.googlecode.garbagecan.test.socket.SerializableUtil; 
 
public class MyServer3 { 
 
  private final static Logger logger = Logger.getLogger(MyServer3.class.getName()); 
   
  public static void main(String[] args) { 
    Selector selector = null; 
    ServerSocketChannel serverSocketChannel = null; 
     
    try { 
      // Selector for incoming time requests 
      selector = Selector.open(); 
 
      // Create a new server socket and set to non blocking mode 
      serverSocketChannel = ServerSocketChannel.open(); 
      serverSocketChannel.configureBlocking(false); 
       
      // Bind the server socket to the local host and port 
      serverSocketChannel.socket().setReuseAddress(true); 
      serverSocketChannel.socket().bind(new InetSocketAddress(10000)); 
       
      // Register accepts on the server socket with the selector. This 
      // step tells the selector that the socket wants to be put on the 
      // ready list when accept operations occur, so allowing multiplexed 
      // non-blocking I/O to take place. 
      serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); 
   
      // Here's where everything happens. The select method will 
      // return when any operations registered above have occurred, the 
      // thread has been interrupted, etc. 
      while (selector.select() > 0) { 
        // Someone is ready for I/O, get the ready keys 
        Iterator<SelectionKey> it = selector.selectedKeys().iterator(); 
   
        // Walk through the ready keys collection and process date requests. 
        while (it.hasNext()) { 
          SelectionKey readyKey = it.next(); 
          it.remove(); 
           
          // The key indexes into the selector so you 
          // can retrieve the socket that's ready for I/O 
          execute((ServerSocketChannel) readyKey.channel()); 
        } 
      } 
    } catch (ClosedChannelException ex) { 
      logger.log(Level.SEVERE, null, ex); 
    } catch (IOException ex) { 
      logger.log(Level.SEVERE, null, ex); 
    } finally { 
      try { 
        selector.close(); 
      } catch(Exception ex) {} 
      try { 
        serverSocketChannel.close(); 
      } catch(Exception ex) {} 
    } 
  } 
 
  private static void execute(ServerSocketChannel serverSocketChannel) throws IOException { 
    SocketChannel socketChannel = null; 
    try { 
      socketChannel = serverSocketChannel.accept(); 
      MyRequestObject myRequestObject = receiveData(socketChannel); 
      logger.log(Level.INFO, myRequestObject.toString()); 
       
      MyResponseObject myResponseObject = new MyResponseObject( 
          "response for " + myRequestObject.getName(),  
          "response for " + myRequestObject.getValue()); 
      sendData(socketChannel, myResponseObject); 
      logger.log(Level.INFO, myResponseObject.toString()); 
    } finally { 
      try { 
        socketChannel.close(); 
      } catch(Exception ex) {} 
    } 
  } 
   
  private static MyRequestObject receiveData(SocketChannel socketChannel) throws IOException { 
    MyRequestObject myRequestObject = null; 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    ByteBuffer buffer = ByteBuffer.allocate(1024); 
     
    try { 
      byte[] bytes; 
      int size = 0; 
      while ((size = socketChannel.read(buffer)) >= 0) { 
        buffer.flip(); 
        bytes = new byte[size]; 
        buffer.get(bytes); 
        baos.write(bytes); 
        buffer.clear(); 
      } 
      bytes = baos.toByteArray(); 
      Object obj = SerializableUtil.toObject(bytes); 
      myRequestObject = (MyRequestObject)obj; 
    } finally { 
      try { 
        baos.close(); 
      } catch(Exception ex) {} 
    } 
    return myRequestObject; 
  } 
 
  private static void sendData(SocketChannel socketChannel, MyResponseObject myResponseObject) throws IOException { 
    byte[] bytes = SerializableUtil.toBytes(myResponseObject); 
    ByteBuffer buffer = ByteBuffer.wrap(bytes); 
    socketChannel.write(buffer); 
  } 
} 

上面是Client的代碼,代碼比擬復雜就是啟動了100個線程來訪問Server

package com.googlecode.garbagecan.test.socket.nio; 
 
import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import java.net.InetSocketAddress; 
import java.net.SocketAddress; 
import java.nio.ByteBuffer; 
import java.nio.channels.SocketChannel; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
 
import com.googlecode.garbagecan.test.socket.SerializableUtil; 
 
public class MyClient3 { 
 
  private final static Logger logger = Logger.getLogger(MyClient3.class.getName()); 
   
  public static void main(String[] args) throws Exception { 
    for (int i = 0; i < 100; i++) { 
      final int idx = i; 
      new Thread(new MyRunnable(idx)).start(); 
    } 
  } 
   
  private static final class MyRunnable implements Runnable { 
     
    private final int idx; 
 
    private MyRunnable(int idx) { 
      this.idx = idx; 
    } 
 
    public void run() { 
      SocketChannel socketChannel = null; 
      try { 
        socketChannel = SocketChannel.open(); 
        SocketAddress socketAddress = new InetSocketAddress("localhost", 10000); 
        socketChannel.connect(socketAddress); 
 
        MyRequestObject myRequestObject = new MyRequestObject("request_" + idx, "request_" + idx); 
        logger.log(Level.INFO, myRequestObject.toString()); 
        sendData(socketChannel, myRequestObject); 
         
        MyResponseObject myResponseObject = receiveData(socketChannel); 
        logger.log(Level.INFO, myResponseObject.toString()); 
      } catch (Exception ex) { 
        logger.log(Level.SEVERE, null, ex); 
      } finally { 
        try { 
          socketChannel.close(); 
        } catch(Exception ex) {} 
      } 
    } 
 
    private void sendData(SocketChannel socketChannel, MyRequestObject myRequestObject) throws IOException { 
      byte[] bytes = SerializableUtil.toBytes(myRequestObject); 
      ByteBuffer buffer = ByteBuffer.wrap(bytes); 
      socketChannel.write(buffer); 
      socketChannel.socket().shutdownOutput(); 
    } 
 
    private MyResponseObject receiveData(SocketChannel socketChannel) throws IOException { 
      MyResponseObject myResponseObject = null; 
      ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
       
      try { 
        ByteBuffer buffer = ByteBuffer.allocateDirect(1024); 
        byte[] bytes; 
        int count = 0; 
        while ((count = socketChannel.read(buffer)) >= 0) { 
          buffer.flip(); 
          bytes = new byte[count]; 
          buffer.get(bytes); 
          baos.write(bytes); 
          buffer.clear(); 
        } 
        bytes = baos.toByteArray(); 
        Object obj = SerializableUtil.toObject(bytes); 
        myResponseObject = (MyResponseObject) obj; 
        socketChannel.socket().shutdownInput(); 
      } finally { 
        try { 
          baos.close(); 
        } catch(Exception ex) {} 
      } 
      return myResponseObject; 
    } 
  } 
} 

最後測試下面的代碼,首先運轉Server類,然後運轉Client類,就可以辨別在Server端和Client端控制台看到發送或接納到的MyRequestObject或MyResponseObject對象了。

以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支持。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved