欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java使用NIO包實(shí)現(xiàn)Socket通信的實(shí)例代碼

 更新時(shí)間:2017年02月06日 17:16:40   作者:kongxx  
本篇文章主要介紹了Java使用NIO包實(shí)現(xiàn)Socket通信的實(shí)例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

前面幾篇文章介紹了使用java.io和java.net類庫實(shí)現(xiàn)的Socket通信,下面介紹一下使用java.nio類庫實(shí)現(xiàn)的Socket。

java.nio包是Java在1.4之后增加的,用來提高I/O操作的效率。在nio包中主要包括以下幾個(gè)類或接口:

  •  Buffer:緩沖區(qū),用來臨時(shí)存放輸入或輸出數(shù)據(jù)。
  •  Charset:用來把Unicode字符編碼和其它字符編碼互轉(zhuǎn)。
  •  Channel:數(shù)據(jù)傳輸通道,用來把Buffer中的數(shù)據(jù)寫入到數(shù)據(jù)源,或者把數(shù)據(jù)源中的數(shù)據(jù)讀入到Buffer。
  •  Selector:用來支持異步I/O操作,也叫非阻塞I/O操作。

nio包中主要通過下面兩個(gè)方面來提高I/O操作效率:

  •  通過Buffer和Channel來提高I/O操作的速度。
  •  通過Selector來支持非阻塞I/O操作。

下面來看一下程序中是怎么通過這些類庫實(shí)現(xiàn)Socket功能。

首先介紹一下幾個(gè)輔助類

輔助類SerializableUtil,這個(gè)類用來把java對象序列化成字節(jié)數(shù)組,或者把字節(jié)數(shù)組反序列化成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,這兩個(gè)類是普通的java對象,實(shí)現(xiàn)了Serializable接口。MyRequestObject類是Client發(fā)出的請求,MyResponseObject是Server端作出的響應(yīng)。

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的代碼,代碼比較簡單就是啟動(dòng)了100個(gè)線程來訪問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; 
    } 
  } 
} 

最后測試上面的代碼,首先運(yùn)行Server類,然后運(yùn)行Client類,就可以分別在Server端和Client端控制臺(tái)看到發(fā)送或接收到的MyRequestObject或MyResponseObject對象了。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • java中的分布式事務(wù)解決方式

    java中的分布式事務(wù)解決方式

    分布式事務(wù)是分布式系統(tǒng)中確保數(shù)據(jù)一致性的重要機(jī)制,它涉及多個(gè)數(shù)據(jù)源或參與者,要么所有操作全部成功,要么全部失敗,常見的解決方案包括2PC(兩階段提交協(xié)議)、3PC(三階段提交協(xié)議)和TCC(Try-Confirm-Cancel),2PC雖然簡單但存在單點(diǎn)故障等問題
    2024-09-09
  • Java使用字節(jié)流實(shí)現(xiàn)圖片音頻的復(fù)制

    Java使用字節(jié)流實(shí)現(xiàn)圖片音頻的復(fù)制

    今天帶大家學(xué)習(xí)Java的相關(guān)知識(shí),文章圍繞著Java如何使用字節(jié)流實(shí)現(xiàn)圖片音頻的復(fù)制展開,文中有非常詳細(xì)的介紹,需要的朋友可以參考下
    2021-06-06
  • MyBatis查詢數(shù)據(jù)返回null的解決

    MyBatis查詢數(shù)據(jù)返回null的解決

    本文主要介紹了MyBatis查詢數(shù)據(jù)返回null的解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • SpringBoot 創(chuàng)建容器的實(shí)現(xiàn)

    SpringBoot 創(chuàng)建容器的實(shí)現(xiàn)

    這篇文章主要介紹了SpringBoot 創(chuàng)建容器的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • 利用Java和c語言寫一個(gè)計(jì)算器

    利用Java和c語言寫一個(gè)計(jì)算器

    這篇文章我們就來分享如何利用Java和c語言來寫一個(gè)計(jì)算器,文章附有代碼詳細(xì)說明,感興趣得小伙伴可以參考下面文章得具體內(nèi)容
    2021-10-10
  • mybatis學(xué)習(xí)筆記之mybatis注解配置詳解

    mybatis學(xué)習(xí)筆記之mybatis注解配置詳解

    本篇文章主要介紹了mybatis學(xué)習(xí)筆記之mybatis注解配置詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-12-12
  • SpringBoot操作mongo實(shí)現(xiàn)方法解析

    SpringBoot操作mongo實(shí)現(xiàn)方法解析

    這篇文章主要介紹了SpringBoot操作mongo實(shí)現(xiàn)方法解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • Java String類詳解_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java String類詳解_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要介紹了Java String類詳解,本文經(jīng)多方資料的收集整理和歸納,最終撰寫成文,非常不錯(cuò),值得收藏,需要的的朋友參考下
    2017-04-04
  • Java SimpleDateFormat線程安全問題原理詳解

    Java SimpleDateFormat線程安全問題原理詳解

    這篇文章主要介紹了Java SimpleDateFormat線程安全問題原理詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • Spring框架學(xué)習(xí)之Cache抽象詳解

    Spring框架學(xué)習(xí)之Cache抽象詳解

    這篇文章主要為大家介紹了Spring框架學(xué)習(xí)中Cache抽象詳解示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2021-10-10

最新評論