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 ...
随机推荐
- 《大规模 web服务开发》笔记
大规模服务: 可扩展,负载均衡,保证冗余,低运维成本,开发人数和开发方法的变化 数据处理: 磁盘—>内存—>缓存—>CPU 障碍: 持续增长的服务,”无法在内 ...
- SQL 隔离级别
在SQL标准中定义了四种隔离级别,每一种级别都规定了一个事务中所做的修改,哪些在事务内和事务间是可见的,哪些是不可见的.较低级别的隔离通常可以执行更高的并发,系统的开销也更低. 简单的介绍四种隔离级别 ...
- Maven搭建Struts2+Spring3+Hibernate4框架
做了三年多的JavaEE开发了,在平时的JavaEE开发中,为了能够用最快的速度开发项目,一般都会选择使用Struts2,SpringMVC,Spring,Hibernate,MyBatis这些开源框 ...
- destoon 短信发送函数及短信接口修改
// $DT在common.inc.php中定义, $CACHE = cache_read('module.php'); $DT = $CACHE['dt']; 从缓存里读取网站配置信息. //$d ...
- LeetCode(260) Single Number III
题目 Given an array of numbers nums, in which exactly two elements appear only once and all the other ...
- centos7 安全配置
CentOS是最多人用来运行服务器的 Linux 版本,最新版本是 CentOS 7.当你兴趣勃勃地在一台主机或 VPS 上安装 CentOS 7 后,首要的工作肯定是加强它的安全性,以下列出的七件事 ...
- Root CA certificate:ApacheJMeterTemporaryRootCA.crt created in JMeter bin directory
今天学习jmeter录制,在点击start之后弹出: 且在jmeter安装目录里确实生成了ApacheJMeterTemporaryRootCA.crt文件 上网查询官方文档http://120.52 ...
- Asp.net HttpWebRequest和HttpWebResponse发送和接受任何类型数据
发送字符串数据发送数据 string strId = "guest"; "; string postData = "userid=" + strId; ...
- I love you
while(true) { printf("I love you"); } 字母解析 I-Inject--投入 投入,这个投入有很多概念,有对自己所爱的人,投入自己所有的感情,让你 ...
- 令人惊叹的Npm工具包
1.http-server (简单搭建http服务器) 2.json-server (JSON服务器,快速搭建resful api接口) 3.cssnano (css多功能优化工具) PS:比uncs ...