Java Socket IO(BIO、NIO)
总结下Java socket IO。首先是各种IO的定义,这个定义似乎也是众说纷纭。我按照stackoverflow上面的解释:
IO有两种分法:按照阻塞或者按照同步。按照阻塞,有阻塞IO和非阻塞IO。按照同步就是同步IO或者异步IO。我们可以认为阻塞IO和同步IO相等,而非阻塞IO和异步IO不同。
阻塞IO或者同步IO是指:IO的请求发出去之后,请求者一直在等待回复,当IO的数据回来到来之后,请求者就开始接受数据。阻塞的意思就是:IO请求发出去之后请求线程就停止在那里,一直等待数据到来。
非阻塞则是:IO请求发出去之后,会立刻收到回复,这个回复可能是IO可以立即进行,或者是无法进行IO的错误。所以非阻塞IO请求者必须一直调用那个API,一直到API返回可以进行IO的信号。
异步IO:IO请求发出之后,后台会建立一个进程,处理IO,当IO都处理完之后,把处理完的数据交给IO的请求者。
本文用Java socket实现阻塞和非阻塞IO(这里大部分内容都学习自千与的专栏,这是位大牛,居然hadoop源码分析写了19篇博客)。然后本文章的所有代码我都放在Github上了。
阻塞IO
阻塞IO比较简单,就是用普通的socket去写,因为没有什么太复杂的处理。建立一个socket,然后,获取它的inputstream和outputstream,然后进行读写操作。
Server端主要代码,handleSocket就是从socket里面读取数据,然后向client写数据:
ServerSocket serverSocket = new ServerSocket(port);
while (true) {
socket = serverSocket.accept();
handleSocket(socket);
}
Client只是简单的发送一句消息:
socket = new Socket(host, port);
out = socket.getOutputStream();
out.write(data);
out.flush();
in = socket.getInputStream();
byte[] buffer = new byte[128];
int receivedBytes;
if((receivedBytes = in.read(buffer))!=-1){
System.out.println("Client: received msg from server: " + new String(buffer, 0, receivedBytes));
}
同时client5000个,使用了大概5s。然后还可以使用多线程Server,就是在每一个client到的时候分配一个线程来处理这个IO,理论上可以增加效率,但是似乎是因为每次处理时间太短,效果不明显。主要代码:
boolean flag = false;
int count = 0;
ServerSocket serverSocket = new ServerSocket(port);
Date start = null;
while (true) {
socket = serverSocket.accept();
if (!flag) {
start = new Date();
flag = true;
}
pool.execute(new RequestHandler(socket));
if(++count== threadCount){
flag = false;
Date end = new Date();
System.out.println(threadCount+" client requests spends: " + (end.getTime() -start.getTime()));
}
}
其中的pool是ExecutorService,提供线程池,然后RequestHandler是一个Runnable类,用来处理一个socket连接。简单讲来,就是把前面server处理socket的代码放到了这个handler里面。
NIO,非阻塞IO
我认定Java的NIO包实现的是同步非阻塞IO,也有人说不是,至少我这里这么认为。在server端,首先打开一个channel,然后向其中注册一个selector,这个selector会在channel中轮询注册的事件,然后根据事件的类型作出处理。一般事件的类型有Accept、read、write。
在Client端也可以是一样的注册,然后通过和server同样的处理方式处理事件(但是没有accept事件,因为只有server才能accept的)。但是我的例子里面只是简单的发送了一条消息。
Server的主要代码:
Selector selector = Selector.open();
ServerSocketChannel serverSocketChannel = ServerSocketChannel
.open();
serverSocketChannel.configureBlocking(false);
serverSocketChannel.socket().bind(address);
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
log.info("Server: socket server started!");
while (true) {
int nKeys = selector.select();
if (nKeys > 0) {
Set selectedKeys = selector.selectedKeys();
Iterator it = selectedKeys.iterator();
while (it.hasNext()) {
SelectionKey key = (SelectionKey) it.next();
if (key.isAcceptable()) {
log.info("Server: Selection key is acceptable");
handler.handleAccept(key);
} else if (key.isReadable()) {
log.info("Server: Selection key is readable");
handler.handleRead(key);
} else if (key.isWritable()) {
log.info("Server: Selection key is writable");
handler.handleWrite(key);
}
it.remove();
}
}
}
其中的handler就是处理每种类型的事件的类,举个Read的例子:
public void handleRead(SelectionKey key) throws IOException {
ByteBuffer byteBuffer = ByteBuffer.allocate(512);
SocketChannel socketChannel = (SocketChannel) key
.channel();
while (true) {
int readBytes = socketChannel.read(byteBuffer);
if (readBytes > 0) {
log.info("Server: readBytes = " + readBytes);
log.info("Server: data = " + new String(byteBuffer.array(), 0, readBytes));
byteBuffer.flip();
socketChannel.write(byteBuffer);
break;
}
}
socketChannel.close();
}
Client就比较简单了,就是用channel直接发送了一句消息:
public void send(String data) {
try {
SocketChannel socketChannel = SocketChannel.open(inetSocketAddress);
socketChannel.configureBlocking(false);
ByteBuffer byteBuffer = ByteBuffer.allocate(512);
socketChannel.write(ByteBuffer.wrap(data.getBytes()));
while (true) {
byteBuffer.clear();
int readBytes = socketChannel.read(byteBuffer);
if (readBytes > 0) {
byteBuffer.flip();
log.info("Client: readBytes = " + readBytes);
log.info("Client: data = " + byteBuffer.toString());
socketChannel.close();
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
最后,这些Java的socket编程在实际工程中已经很少使用了,由于Unix的poll等功能的出现,select相比较之下,有点弱了。接下来可以考虑研究下。
NIO包的API介绍:
http://wufan0023.iteye.com/blog/198722
http://wufan0023.iteye.com/blog/198710
- 分享到:
This entry was posted in Java topic and tagged Java, socket by 柳浪闻莺. Bookmark the permalink.
Java Socket IO(BIO、NIO)的更多相关文章
- 深入分析JAVA IO(BIO、NIO、AIO)
IO的基本常识 1.同步 用户进程触发IO操作并等待或者轮询的去查看IO操作是否完成 2.异步 用户触发IO操作以后,可以干别的事,IO操作完成以后再通知当前线程继续处理 3.阻塞 当一个线程调用 r ...
- 【转】深入分析JAVA IO(BIO、NIO、AIO)
IO的基本常识 1.同步 用户进程触发IO操作并等待或者轮询的去查看IO操作是否完成 2.异步 用户触发IO操作以后,可以干别的事,IO操作完成以后再通知当前线程继续处理 3.阻塞 当一个线程调用 r ...
- JAVA SOCKET 通信总结 BIO、NIO、AIO ( NIO 2) 的区别和总结
1 同步 指的是用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪 自己上街买衣服,自己亲自干这件事,别的事干不了.2 异步 异步是指用户进程触发IO操作以后便开始做自己的事情,而当IO操作已 ...
- Java网络通信方面,BIO、NIO、AIO、Netty
码云项目源码地址:https://gitee.com/ZhangShunHai/echo 教学视频地址:链接: https://pan.baidu.com/s/1knVlW7O8hZc8XgXm1dC ...
- Java IO 之 BIO、NIO、AIO
1.BIO.NIO.AIO解释 Java BIO : 同步并阻塞 (Blocking IO) 一个连接一个线程 即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不 ...
- tomcat并发优化之三种接收处理请求方式(BIO、NIO、APR)介绍
原文链接:http://blog.csdn.net/xyang81/article/details/51502766 Tomcat支持三种接收请求的处理方式:BIO.NIO.APR 1>.BIO ...
- (转)Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)
原文出自:http://blog.csdn.net/anxpp/article/details/51512200 1.BIO编程 1.1.传统的BIO编程 网络编程的基本模型是C/S模型,即两个进程间 ...
- Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)
本文会从传统的BIO到NIO再到AIO自浅至深介绍,并附上完整的代码讲解. 下面代码中会使用这样一个例子:客户端发送一段算式的字符串到服务器,服务器计算后返回结果到客户端. 代码的所有说明,都直接作为 ...
- Java 网络IO编程(BIO、NIO、AIO)
本概念 BIO编程 传统的BIO编程 代码示例: public class Server { final static int PROT = 8765; public static void main ...
随机推荐
- win7便笺元数据损坏,最新解决办法
Windows7系统开机时出现“部分便笺的元数据已被破坏,便笺已将其恢复为默认值.”问题,最新解决办法,图文说明,亲测,希望可以帮到大家 工具/原料 Windows7系统 InkObj.dll.T ...
- SC || Chapter6 复习向 面向可维护性 我哭了
高内聚低耦合 高内聚:一个模块内部各个元素彼此结合的紧密程度,一个软件模块是由相关性很强的代码组成,只负责一项任务,也就是常说的单一责任原则 低耦合:各模块间相互联系紧密程度,模块间接口的复杂性.调用 ...
- windbg双机调试配置
环境 虚拟机 win7 Pro x86 vmware 12 windbg x86 虚拟机win7配置 管理员权限运行cmd.exe 然后输入以下命令: bcdedit /? bcdedit /enum ...
- C#MySQL增删改查
首先在项目中添加引用 using MySql.Data.MySqlClient; 连接字符串 private string connString="server=localhost;use ...
- 理解JS闭包的几个小实验
学了JavaScript有一段时间了,但是对闭包还是不太理解,于是怀着心中的疑问做了几个小实验,终于有点明白了. 首先看一下MDN上的定义:闭包是函数和声明该函数的词法环境的组合. 简单来说,闭包是一 ...
- linux文件属性文文件类型知识
文件类型分别介绍: 1.普通文件:我们通过用ls -l来查看xxx.sql的属性,可以看到第一列内容为-rw-r--r--,值得注意的是第一个符号是-(英文字符减号),在Linux中,以这样的字符开 ...
- jQuery 淡入淡出有png图的时候 ie8下有黑色边框
jQuery fadeTo 时ie8 png图片有黑色边框 往带有png图的样式里加 filter:progid:DXImageTransform.Microsoft.AlphaImageLoader ...
- apicloud入门学习笔记1:简单介绍
官网地址:https://www.apicloud.com/ 新手开发指南:https://docs.apicloud.com/APICloud/junior-develop-guide 开发语言:H ...
- MIP启发式算法:Variable Neighborhood Decomposition Search
*本文记录和分享学习到的知识,算不上原创. *参考文献见链接. 本文主要简述和VND VNS RINS很相关的vairable neighborhood decomposition search. 目 ...
- BZOJ 5313: 新Fib数列
打表找规律 #include<cstdio> using namespace std; int F[20]={0,1,1,2,3,0,3,3,1,4,0,4,4,3,2,0,2,2,4,1 ...