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 ...
随机推荐
- webpack 中文文档
webpack 最强最详细中文文档 https://doc.webpack-china.org/guides/getting-started/#- webpack多页应用架构系列 http://web ...
- 爬虫3:requests库
一个简单易用的http库,多用于第一步,爬取网站源码 简单例子 import requests response = requests.get('https://www.baidu.com ...
- 如何在CentOS 7上使用vsftpd(FTP)的配置文件介绍
vsftpd.conf - vsftpd的配置文件. 描述 vsftpd.conf可用于控制vsftpd行为的各个方面. 默认情况下,vsftpd在/etc/vsftpd.conf位置查找此文件. 但 ...
- LLDB 和Chisel 使用例子
打印变量 打印数字 (lldb) p/d 16 16 16 进制格式 (lldb) p/x 16 0x10 2 进制格式 (lldb) p/t 16 0b00000000000000000000000 ...
- HQL的使用和limit的替代
1.HQL不同于SQL,from必须是项目中table反转后对应的class的名字. 2.如何使用参数生成HQL语句: String hql = "from User where userI ...
- 【Python】解析Python的标准数据类型
目录结构: contents structure [-] 数值(Number) 数值类型 类型转化 Python中的Decimal数据类型 Python中的分数 Python中的算术方法 字符串(St ...
- Python 全栈开发:day3 作业与默写
# 1.有变量name = "aleX leNb" 完成如下操作:name = 'aleX leNb'# 1)移除 name 变量对应的值两边的空格,并输出处理结果print(na ...
- TP5 隐藏入口文件 index.php
找到public下的.htaccess <IfModule mod_rewrite.c> Options +FollowSymlinks -Multiviews RewriteEngine ...
- 四大组件之Activity——生命周期
1.完整的Activity生命周期 包括onCreate() -> onStart() -> onResume() -> onPause() -> onStop -> o ...
- redis 数据库迁移
老大让把 一台机器上 redis 中所有的数据,迁移到另一台机器上 查了一下可以拷贝 rdb 文件, 此方法只适用于迁移到一个新的库, 迁移到正在使用的库就不行了, 而且 rdb 里面是所有的 db, ...