前面几篇文章介绍了使用java.io和java.net类库实现的Socket通信,下面介绍一下使用java.nio类库实现的Socket。

java.nio包是Java在1.4之后增加的,用来提高I/O操作的效率。在nio包中主要包括以下几个类或接口:
nio包中主要通过下面两个方面来提高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小时内与您取得联系。