socker TCP UDP BIO NIO
BIO: Java 1.4 以前只有之中方式。
bio:阻塞式IO, 一个 socker 连接占用一个 线程。如果 IO 阻塞,会在传输速度限制,这个线程也会一直等待在这里,等待从socker 的 IO 流 中读写数据。
Java 基于 socker 的 连接方式都是 BIO,都是阻塞式的IO。
TCP:
server:
ServerSocket ss = new ServerSocket(20000);
while( true ) {
Socket socket = ss.accept();
List<String> datas = IOUtils.readLines( socket.getInputStream() );
System.out.println( datas.get(0) );
socket.close(); }
cilent:
Socket socket = new Socket("127.0.0.1", 20000);
IOUtils.write("hello", socket.getOutputStream() );
socket.getOutputStream().flush();
socket.getOutputStream().close();
socket.close();
原理图:
UDP:
server:
DatagramSocket ds = new DatagramSocket(20000);
while( true ) {
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
ds.receive( dp );
System.out.println( new String(dp.getData()) );
}
client:
DatagramSocket ds = new DatagramSocket();
String data = "hello";
DatagramPacket dp = new DatagramPacket(data.getBytes(),data.length(),InetAddress.getLocalHost(),20000);
ds.send(dp);
NIO: Java 1.4 以后支持的IO方式
NIO: 非阻塞式的IO, NIO 不再是 传统socker 方式。 一个 IO请求过来,会有一个线程,来处理这个IO请求,但是如果这个IO阻塞,那么这个线程会被处理别的 IO请求的 的事情。如果阻塞的IO的操作完成(完成一个块数据写入缓冲区),那么就会有一个线程分配过来处理这部分数据。
selecter: NIO 不再是 传统socke的概念。 socker 一个 连接,就固定一个 线程来处理,并且这个线程值服务这个 socker。但是 NIO 改变了这种IO 模型, selecter 里面跑着一个独立的线程,这个线程管理 一些渠道( channel , 有点 类似 socker ),如果 某个
渠道的 数据准备好了,那么 selecter 就会分配一个线程来 读写 这个channet 的数据。
buffer: 前面 一直强调 当数据准备好了,什么样才叫数据准备好了? socker 方式的 io 模式是一个 字节 一个字节读写的。 NIO 是通过 一块一块读写的( 一块就是 多个字节 ),但是这个这个 一块数据是 需要 一个临时存放区域的,这就是buffer 。当一个 块 数据满了以后,就分配 线程 来执行这个请求。
channel: 相当于以前的 流的 概念,可以 李杰成一个管道。BIO 一个连接一个线程,并且在socker结束以前一直占用着这个线程。NIO 是一个 也是一个连接一个线程。但是这个线程不会一直 等待这个 连接的IO操作。
例子代码:
server:
package comcxygg.test.nio; import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID; public class NioServer {
public static void main(String[] args) throws Exception {
/**
* 开启一个服务端
* 设置为非阻塞
* 绑定端口号
*/
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.configureBlocking(false);
serverSocketChannel.bind(new InetSocketAddress(8080)); System.out.println("serverSocketChannel:" + serverSocketChannel.hashCode() );
Selector selector = Selector.open();
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
//UUID->客户端连接
Map<String,SocketChannel> clientMap = new HashMap<>(); while (true) {
selector.select(); Set<SelectionKey> selectionKeys = selector.selectedKeys();
selectionKeys.forEach(selectionKey -> { try {
if (selectionKey.isAcceptable()) {
/**
* 服务端接收到连接
* 保存接收到的客户端连接
*/
ServerSocketChannel server = (ServerSocketChannel) selectionKey.channel();
System.out.println("server:" + server.hashCode() ); SocketChannel socketChannel = server.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector,SelectionKey.OP_READ);
String key = UUID.randomUUID().toString();
clientMap.put(key,socketChannel);
System.out.println(socketChannel.getRemoteAddress()+"连接上了服务器");
} else if (selectionKey.isReadable()) {
/**
* 读取客户端消息
* 转发到所有客户端
*/
SocketChannel socketChannel = (SocketChannel) selectionKey.channel(); System.out.println( "服务器端socketChannel:" + socketChannel.hashCode());
try {
ByteBuffer buffer = ByteBuffer.allocate(1024);
int len = socketChannel.read(buffer); if (len > 0) {
buffer.flip();
Charset charset = Charset.forName("UTF-8");
String receiveMsg = String.valueOf(charset.decode(buffer).array());
String key = null;
for (Map.Entry<String,SocketChannel> entry : clientMap.entrySet()) {
if (entry.getValue() == socketChannel) {
key = entry.getKey();
break;
}
}
String sendMsg = key + ":" + receiveMsg;
System.out.println(sendMsg);
ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
writeBuffer.put(sendMsg.getBytes());
writeBuffer.flip();
clientMap.get(key).write( writeBuffer );
/* for (Map.Entry<String,SocketChannel> entry : clientMap.entrySet()) {
ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
writeBuffer.put(sendMsg.getBytes());
writeBuffer.flip();
entry.getValue().write(writeBuffer);
}*/
}
}catch (Exception e) {
e.printStackTrace();//java.io.IOException: 远程主机强迫关闭了一个现有的连接。
socketChannel.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
});
selectionKeys.clear();
} }
}
client:
package comcxygg.test.nio; import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class NioClient {
public static void main(String[] args) throws Exception {
/**
* 开启一个客户端
* 设置为非阻塞
* 连接到服务器
*/
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
socketChannel.connect(new InetSocketAddress("localhost",8080)); Selector selector = Selector.open();
socketChannel.register(selector, SelectionKey.OP_CONNECT); System.out.println( "socketChannel:" + socketChannel.hashCode() ); while (true) {
selector.select(); Set<SelectionKey> selectionKeys = selector.selectedKeys();
for (SelectionKey selectionKey : selectionKeys) {
if (selectionKey.isConnectable()) {
/**
* 客户端已连接
* 开启一个线程监听控制台输入
*/
SocketChannel client = (SocketChannel) selectionKey.channel();
System.out.println( "client1:" + client.hashCode() );
if (client.isConnectionPending()) {
client.finishConnect();
}
client.register(selector,SelectionKey.OP_READ);
ExecutorService executor = Executors.newSingleThreadExecutor();
System.out.println(socketChannel.getLocalAddress()+"连上了服务器");
ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
executor.submit(()->{
try {
while (true) {
writeBuffer.clear();
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String line = reader.readLine();
writeBuffer.put(line.getBytes());
writeBuffer.flip();
client.write(writeBuffer);
}
}catch (Exception e) {
e.printStackTrace();
}
});
} else if (selectionKey.isReadable()) { /**
* 打印服务端消息
*/
SocketChannel client = (SocketChannel) selectionKey.channel();
System.out.println( "client2:" + client.hashCode() );
ByteBuffer readBuffer = ByteBuffer.allocate(1024);
int len = client.read(readBuffer);
System.out.println(new String(readBuffer.array(),0,len));
}
}
selectionKeys.clear();
}
}
}
BIO 图:

NIO 的 UDP 协议使用:
别的基本一样 只是 渠道使用的 DatagramChannel 。
socker TCP UDP BIO NIO的更多相关文章
- 拿搬东西来解释udp tcpip bio nio aio aio异步
[群主]雷欧纳德简单理解 tcpip是有通信确认的面对面通信 有打招呼的过程 有建立通道的过程 有保持通道的确认 有具体传输udp是看到对面的人好像在对面等你 就往对面扔东西[群主]雷欧 ...
- Netty5序章之BIO NIO AIO演变
Netty5序章之BIO NIO AIO演变 Netty是一个提供异步事件驱动的网络应用框架,用以快速开发高性能.高可靠的网络服务器和客户端程序.Netty简化了网络程序的开发,是很多框架和公司都在使 ...
- Netty序章之BIO NIO AIO演变
Netty序章之BIO NIO AIO演变 Netty是一个提供异步事件驱动的网络应用框架,用以快速开发高性能.高可靠的网络服务器和客户端程序.Netty简化了网络程序的开发,是很多框架和公司都在使用 ...
- BIO & NIO & NIO常见框架
BIO & NIO BIO - Blocking IO - 同步式阻塞式IO --- UDP/TCP NIO - New IO - 同步式非阻塞式IO AIO - Asynchronous ...
- tomcat bio nio apr 模式性能测试
转自:tomcat bio nio apr 模式性能测试与个人看法 11.11活动当天,服务器负载过大,导致部分页面出现了不可访问的状态.那后来主管就要求调优了,下面是tomcat bio.nio.a ...
- I/O模型系列之三:IO通信模型BIO NIO AIO
一.传统的BIO 网络编程的基本模型是Client/Server模型,也就是两个进程之间进行相互通信,其中服务端提供位置信息(绑定的IP地址和监听端口),客户端通过连接操作向服务端监听的地址发起连接请 ...
- BIO,NIO与AIO的区别
Java NIO : 同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理.Java AIO(NIO.2 ...
- 【netty】(1)---BIO NIO AIO演变
BIO NIO AIO演变 Netty是一个提供异步事件驱动的网络应用框架,用以快速开发高性能.高可靠的网络服务器和客户端程序.Netty简化了网络程序的开发,是很多框架和公司都在使用的技术. Net ...
- Java提供了哪些IO方式?IO, BIO, NIO, AIO是什么?
IO一直是软件开发中的核心部分之一,而随着互联网技术的提高,IO的重要性也越来越重.纵观开发界,能够巧妙运用IO,不但对于公司,而且对于开发人员都非常的重要.Java的IO机制也是一直在不断的完善,以 ...
随机推荐
- layui实现批量导入excal表
layui实现多文件上传,并直接选中需要上传文件的类型 //拖拽上传 upload.render({ elem : '#import', size: , //限制文件大小,单位 KB accept: ...
- UVA - 11327
UVA - 11327https://vjudge.net/problem/28358/origin求欧拉函数的前缀和,二分查找到那个位置,再从它开始暴力gcd找 #include <iostr ...
- 分享一个现代的,免费的,简单而有效的编辑器Vis
Vis是一个免费的开源,类似Vi的代码编辑器,它扩展了vi的模态编辑,内置支持使用相同编辑器的基于结构正则表达式的命令语言实现的多个游标/选择.并将其与基于sam结构正则表达式的命令语言相结合. Vi ...
- Vue生命周期的执行过程(面试必备) 极简版
最近准备面试,临时抱佛脚的来回顾一下vue相关的面试题,当然这是不对的,平时还是要努力呀,走起: 1.创建vue实例,Vue(); 2.在创建Vue实例的时候,执行了init(),在init过程中首先 ...
- 洛谷P5104 红包发红包
题目链接: P5104 题目分析: 题目和\(n\)是没什么关系的,因为是\(n\)个人抢,其实不一定抢完 其实很显然--就是求一个连续型随机变量的期望 首先设一个随机变量\(X\),表示第一个人拿到 ...
- opencv-Mat数据类型及位数总结
转自:http://blog.sina.com.cn/s/blog_662c7859010105za.html 在OpenCV里面,许多数据结构为了达到內存使用的最优化,通常都会用它最小上限的空间来分 ...
- express 4 使用session和cookies
https://my.oschina.net/u/1466553/blog/294336 http://blog.csdn.net/liyi109030/article/details/3527138 ...
- shell对文件,文件夹的操作
x=$ OUTFILENAME="output_${x}.sql" if [ -f $OUTFILENAME ];then rm $OUTFILENAME fi 如果文件存在则删除 ...
- PAT甲级——A1003Emergency
As an emergency rescue team leader of a city, you are given a special map of your country. The map s ...
- 08_springmvc数据回显和@ModelAttribute注解详解
一.数据回显 提交后,如果出现错误,将刚才提交的数据回显到刚才的提交页面. 二.pojo数据回显方法 1.springmvc默认对pojo数据进行回显. pojo数据传入controller方法后,s ...