加入收藏 | 设为首页 | 会员中心 | 我要投稿 安卓应用网 (https://www.0791zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

Java使用NIO包实现Socket通信的实例代码

发布时间:2020-05-23 05:53:09 所属栏目:Java 来源:互联网
导读:前面几篇文章介绍了使用java.io和java.net类库实现的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 + ",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,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); 
  } 
} 

(编辑:安卓应用网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读