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 ...
随机推荐
- USB-Redirector-Technician 永久破解版(USB设备映射软件)
USB-Redirector-Technician 这个软件对于搞安卓刷机的人想必非常熟悉,淘宝破解版售价:38 一个的东西 除了远程刷机,用于映射一些小型设备是没问题的,只要网跟得上~ USB-Re ...
- [CISCO] 转载:冲突域与广播域(区别、知识要点)
[CISCO] 转载:冲突域与广播域(区别.知识要点) 1.传统以太网操作(Ethernet Connection Ethernet) 传统共享式以太网的典型代表是总线型以太网.在这种类型的以太网中, ...
- JDK下载与安装、 Eclipse下载与使用的总结心得_20173311118_牛明旺
一.JDK下载与安装心得: ① 从官网http://www.oracl.com/technetwork/java上下载JDK,注意一定要同意该网站上的协议,否则下载不了(即点击“Accept Lic ...
- mac下配置influxdb
influxdb 基本概念 参考:https://docs.influxdata.com/influxdb/v1.4/concepts/key_concepts 基本概念图: Database(绿色白 ...
- C#静态和实例
静态 实例 关键字static修饰类或方法 不能使用static修饰类或方法 修饰后类直接调用 需要先实例化对象,用对象调用 静态只会执行调用一次,并且在程序退出之前会一直保持状态,占领内存 实例化一 ...
- follow up2-20190426
406. Minimum Size Subarray 同向双指针 https://www.lintcode.com/problem/minimum-size-subarray-sum/descript ...
- android4.0以上访问网络不能在主线程中进行以及在线程中操作UI的解决方法
MONO 调用一个线程操作UI 然后报Only the original thread that created a view hierarchy can touch its views.错误 goo ...
- Linux 操作系统常用的三种流012
Linux 操作系统常用的三种流: 0 标准输入流 1 标准输出流 2 标准错误流 通常在写脚本启动程序,写log时候,会出现如下写法: nohup commod > log.txt 2> ...
- <机器学习实战>读书笔记--k邻近算法KNN
k邻近算法的伪代码: 对未知类别属性的数据集中的每个点一次执行以下操作: (1)计算已知类别数据集中的点与当前点之间的距离: (2)按照距离递增次序排列 (3)选取与当前点距离最小的k个点 (4)确定 ...
- C# SocketUdpServer
public interface ISocketUdpServer { void Start(); void Stop(); int SendData(byte[] data, IPEndPoint ...