NIO与Socket
一、Socket 的使用
1、单线程Socket的使用
/**
* 单线程版本
* 问题描述:只能服务单个客户端
* 解决方案:多线程版本
*/
public class Socket_V1 {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(1234);
System.out.println("启动服务器:");
while(true) {
System.out.println("等待客户端链接(阻塞)……");
Socket socket = serverSocket.accept();
System.out.println("有链接进来了……");
handle(socket);
}
}
private static void handle(Socket socket) {
try {
InputStream inputStream = socket.getInputStream();
byte[] b = new byte[1024];
String str = null;
while(true) {
str = null;
System.out.println("等待输入……");
int read = inputStream.read(b);
if(read == -1) {
System.out.println("客户端关闭。");
break;
}
str = new String(b);
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2、多线程版本
/**
* 多线程版本
* 问题描述:多线程开销大
* 解决方案:NIO
*/
public class Socket_V2 { public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(1234);
// 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
ExecutorService threadPool = Executors.newFixedThreadPool(10);
System.out.println("启动服务器:");
while(true) {
System.out.println("等待客户端链接(阻塞)……");
final Socket socket = serverSocket.accept();
System.out.println("有链接进来了……");
//使用线程池来,支持并发
threadPool.execute(new Runnable() {
public void run() {
handle(socket);
}
});
}
}
private static void handle(Socket socket) {
try {
InputStream inputStream = socket.getInputStream();
byte[] b = new byte[1024];
String str = null;
while(true) {
str = null;
System.out.println("等待输入……");
int read = inputStream.read(b);
if(read == -1) {
System.out.println("客户端关闭。");
break;
}
str = new String(b);
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
3、NIO
/**
* NIO版本
* 原理:IO多路复用
* NIO与旧Socket对比:
* ServerSocketChannel <-等价于-> ServerSocket
* SocketChannel <-等价于-> Socket
* Selector 选择器
* SelectionKey 事件类型
*/
public class Socket_NIO {
public static void main(String[] args) throws Exception {
//获得Socket通道
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//将通道设置为非阻塞模式
serverSocketChannel.configureBlocking(false);
//将通道绑定到指定的端口
serverSocketChannel.socket().bind(new InetSocketAddress(1234));
//获取通道选择器
Selector selector = Selector.open();
//将连接事件,注册到选择器内(步骤1)
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("服务器启动成功。端口已经监听……");
while(true) {
selector.select();//阻塞等待已经注册的事件
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while(iterator.hasNext()) {
SelectionKey next = iterator.next();
iterator.remove();
if(next.isAcceptable()) { //如果是连接事件,注册读写事件
System.out.println("获取到连接事件。");
ServerSocketChannel sschannel = (ServerSocketChannel) next.channel(); //该强转是步骤1内存放的值
SocketChannel channel = sschannel.accept(); //获取客户端连接的通道
channel.configureBlocking(false);//设置为非阻塞
channel.register(selector, SelectionKey.OP_READ); //步骤2
}else if(next.isReadable()) { //如果是可读事件,则执行读操作
System.out.println("获取到可读事件。");
SocketChannel channel = (SocketChannel) next.channel(); //获取socket通道,该强转是步骤2内存放的值
ByteBuffer dst = ByteBuffer.allocate(1024); //缓冲区
int read = channel.read(dst);
if(read < 0 ) {
System.out.println("客户端关闭。");
next.cancel();
break;
}
System.out.println("客户端输入:"+new String(dst.array()));
} //还有其他事件……略
}
}
}
}
关于nio的一点理解:
优点:少了线程切换的开销。(io多路复用)
对比多线程模式,线程用完cpu时间片之后,就切换线程。 此时io阻塞的线程(不是就绪状态,无法获取cpu时间片),io非阻塞线程(网速很慢),只能获取到一部分数据,则浪费了相应的cpu时间片。
NIO与Socket的更多相关文章
- 利用NIO建立Socket服务器
传统的Java 的IO,利用Socket建立服务器,接收客户端连接,一般都是为每一个连接建立一个线程,如果连接数巨大,那么服务器开销也将巨大..NIO的原理,可以参照图:http://new.51ct ...
- 基于NIO的Socket通信
一.NIO模式的基本原理: 服务端: 首先,服务端打开一个通道(ServerSocketChannel),并向通道中注册一个通道调度器(Selector):然后向通道调度器注册感兴趣的事件Select ...
- Java NIO 之 Socket Channel
在Java NIO中用Channel来对程序与进行I/O操作主体的连接关系进行抽象,这些IO主体包括如文件.Socket或其他设备.简而言之,指代了一种与IO操作对象间的连接关系. 按照Channel ...
- NIO Channel Socket套接字相关Channel
阻塞非阻塞: NIO中的Channel主要分为两大类:一类是FileChannel,另一类是SocketChannel.NIO提供的核心非阻塞特性主要针对SocketChannel类,全部socket ...
- Java I/O之NIO Socket
PS:本文简单介绍下旧I/O和NIO下的Socket通讯,仅以UDP来示例. TCP/IP协议 首先简单回顾下TCP/IP协议 Application:应用程序:Socket:套接字:Host:主机: ...
- Java NIO4:Socket通道
Socket通道 上文讲述了通道.文件通道,这篇文章来讲述一下Socket通道,Socket通道与文件通道有着不一样的特征,分三点说: 1.NIO的Socket通道类可以运行于非阻塞模式并且是可选择的 ...
- c.BIO连接器与NIO连接器的对比
前面两节,我们分别看了BIO和NIO的两种模式Tomcat的实现方式. BIO的方式,就是传统的一线程,一请求的模式,也就是说,当同时又1000个请求过来,如果Tomcat设置了最大Accept线程数 ...
- Android NIO(Noblocking I/O非阻塞I/O)小结
参考:http://www.cnblogs.com/cpcpc/archive/2011/06/27/2123009.html 对于Android的网络通讯性能的提高,我们可以使用Java上高性能的N ...
- 探索Java NIO
什么是NIO? java.nio全称java non-blocking IO,是指jdk1.4 及以上版本里提供的新api(New IO),NIO提供了与标准IO不同的IO工作方式. 核心部分: Ch ...
随机推荐
- httpclient4.5 https请求 忽略身份验证
import org.apache.commons.collections.MapUtils; import org.apache.http.*; import org.apache.http.cli ...
- C++基础知识-inline、const、mutable、this、static
一.在类定义中实现成员函数inline 类内的成员函实现其实也叫作类内的成员函数定义. 这种直接在类的定义中实现的函数,会被当做inline内联函数来处理. 二.成员函数末尾的const const: ...
- 2016级算法第六次上机-F.AlvinZH的学霸养成记VI
1082 AlvinZH的学霸养成记VI 思路 难题,凸包. 分析问题,平面上给出两类点,问能否用一条直线将二者分离. 首先应该联想到这是一个凸包问题,分别计算两类点的凸包,如果存在符合题意的直线,那 ...
- 使用hexo+coding搭建免费个人博客
1.检测node和npm 先检测一下有没有node.js和npm $ node -v //如果有,说明node.js安装成功! $ node -v v8.4.0 //如果有,说明npm安装成功! $n ...
- 5、Tensorflow基础(三)神经元函数及优化方法
1.激活函数 激活函数(activation function)运行时激活神经网络中某一部分神经元,将激活信息向后传入下一层的神经网络.神经网络之所以能解决非线性问题(如语音.图像识别),本质上就是激 ...
- 原 form 表单中 disabled 属性的元素不参与表单提交
https://blog.csdn.net/benben683280/article/details/79173336
- 前端知识总结--BFC
Block Formatting Context,中文直译为块级格式上下文. 1. BFC的定义 是 W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行定位,以及与其他元素的关系和 ...
- leetcode python找不同
给两个字符串,第二个字符串是第一个字符串乱序后再随机插入一个字母在随机的位置,需要我们找到这个字母 输入: s = "abcd" t = "abcde" 输出: ...
- initializer_list
initializer_list是一种模板类型,定义initializer_list对象是,必须说明列表中所含元素的类型: initializer_list<Type> lst{a, b, ...
- ui7
2016.9讲义 一.课程的主要内容和目的 二.课程所用工具软件——Photoshop CS6 1. Photoshop 的发展史 1990.2,ps1.0问世,1991.2,PS2.0发行,此后,进 ...