全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

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对象了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# java  # nio  # socket  # socket通信  # java实现socket通信  # Java Socket编程实例(四)- NIO TCP实践  # Java NIO实例UDP发送接收数据代码分享  # Java Socket编程实例(五)- NIO UDP实践  # 详解Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)  # Java NIO Path接口和Files类配合操作文件的实例  # Java NIO和IO的区别  # Java 高并发八:NIO和AIO详解  # Java NIO工作原理的全面分析  # 基于java编写局域网多人聊天室  # Java基于中介者模式实现多人聊天室功能示例  # java使用MulticastSocket实现基于广播的多人聊天室  # Java NIO Selector用法详解【含多人聊天室实例】  # 几个  # 类库  # 介绍一下  # 包中  # 是怎么  # 很有  # 这两个  # 英文  # 看一下  # 主要包括  # 也叫  # 两个方面  # 大家多多  # 就可以  # 几篇  # 主要是  # 实现了  # 文档  # 其中有  # 启动了 


相关文章: 太平洋网站制作公司,网络用语太平洋是什么意思?  如何快速查询网站的真实建站时间?  如何用PHP快速搭建CMS系统?  如何在Golang中指定模块版本_使用go.mod控制版本号  手机网站制作平台,手机靓号代理商怎么制作属于自己的手机靓号网站?  太原网站制作公司有哪些,网约车营运证查询官网?  如何用免费手机建站系统零基础打造专业网站?  如何快速配置高效服务器建站软件?  如何在IIS管理器中快速创建并配置网站?  定制建站哪家更专业可靠?推荐榜单揭晓  外汇网站制作流程,如何在工商银行网站上做外汇买卖?  如何快速重置建站主机并恢复默认配置?  如何高效利用亚马逊云主机搭建企业网站?  番禺网站制作公司哪家值得合作,番禺图书馆新馆开放了吗?  盐城做公司网站,江苏电子版退休证办理流程?  ,南京靠谱的征婚网站?  微网站制作教程,不会写代码,不会编程,怎么样建自己的网站?  儿童网站界面设计图片,中国少年儿童教育网站-怎么去注册?  ,网站推广常用方法?  网站专业制作公司有哪些,做一个公司网站要多少钱?  如何通过WDCP绑定主域名及创建子域名站点?  家具网站制作软件,家具厂怎么跑业务?  专业的网站制作设计是什么,如何制作一个企业网站,建设网站的基本步骤有哪些?  免费制作统计图的网站有哪些,如何看待现如今年轻人买房难的情况?  建站主机与服务器功能差异如何区分?  制作网站的公司有哪些,做一个公司网站要多少钱?  宝塔Windows建站如何避免显示默认IIS页面?  黑客如何利用漏洞与弱口令入侵网站服务器?  ppt制作免费网站有哪些,ppt模板免费下载网站?  企业网站制作公司网页,推荐几家专业的天津网站制作公司?  如何在橙子建站上传落地页?操作指南详解  如何在Golang中引入测试模块_Golang测试包导入与使用实践  如何在宝塔面板创建新站点?  如何用PHP快速搭建高效网站?分步指南  深圳网站制作的公司有哪些,dido官方网站?  微课制作网站有哪些,微课网怎么进?  建站之星后台密码遗忘?如何快速找回?  北京营销型网站制作公司,可以用python做一个营销推广网站吗?  如何通过商城自助建站源码实现零基础高效建站?  重庆网站制作公司哪家好,重庆中考招生办官方网站?  c++怎么编写动态链接库dll_c++ __declspec(dllexport)导出与调用【方法】  如何做静态网页,sublimetext3.0制作静态网页?  广平建站公司哪家专业可靠?如何选择?  香港代理服务器配置指南:高匿IP选择、跨境加速与SEO优化技巧  如何选择域名并搭建高效网站?  济南企业网站制作公司,济南社保单位网上缴费步骤?  如何通过.red域名打造高辨识度品牌网站?  如何做网站制作流程,*游戏网站怎么搭建?  如何快速搭建二级域名独立网站?  建站中国官网:模板定制+SEO优化+建站流程一站式指南 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。