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的更多相关文章

  1. 拿搬东西来解释udp tcpip bio nio aio aio异步

     [群主]雷欧纳德简单理解 tcpip是有通信确认的面对面通信   有打招呼的过程  有建立通道的过程 有保持通道的确认    有具体传输udp是看到对面的人好像在对面等你 就往对面扔东西[群主]雷欧 ...

  2. Netty5序章之BIO NIO AIO演变

    Netty5序章之BIO NIO AIO演变 Netty是一个提供异步事件驱动的网络应用框架,用以快速开发高性能.高可靠的网络服务器和客户端程序.Netty简化了网络程序的开发,是很多框架和公司都在使 ...

  3. Netty序章之BIO NIO AIO演变

    Netty序章之BIO NIO AIO演变 Netty是一个提供异步事件驱动的网络应用框架,用以快速开发高性能.高可靠的网络服务器和客户端程序.Netty简化了网络程序的开发,是很多框架和公司都在使用 ...

  4. BIO & NIO & NIO常见框架

    BIO & NIO BIO - Blocking IO - 同步式阻塞式IO --- UDP/TCP NIO - New  IO - 同步式非阻塞式IO AIO  - Asynchronous ...

  5. tomcat bio nio apr 模式性能测试

    转自:tomcat bio nio apr 模式性能测试与个人看法 11.11活动当天,服务器负载过大,导致部分页面出现了不可访问的状态.那后来主管就要求调优了,下面是tomcat bio.nio.a ...

  6. I/O模型系列之三:IO通信模型BIO NIO AIO

    一.传统的BIO 网络编程的基本模型是Client/Server模型,也就是两个进程之间进行相互通信,其中服务端提供位置信息(绑定的IP地址和监听端口),客户端通过连接操作向服务端监听的地址发起连接请 ...

  7. BIO,NIO与AIO的区别

    Java NIO : 同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理.Java AIO(NIO.2 ...

  8. 【netty】(1)---BIO NIO AIO演变

    BIO NIO AIO演变 Netty是一个提供异步事件驱动的网络应用框架,用以快速开发高性能.高可靠的网络服务器和客户端程序.Netty简化了网络程序的开发,是很多框架和公司都在使用的技术. Net ...

  9. Java提供了哪些IO方式?IO, BIO, NIO, AIO是什么?

    IO一直是软件开发中的核心部分之一,而随着互联网技术的提高,IO的重要性也越来越重.纵观开发界,能够巧妙运用IO,不但对于公司,而且对于开发人员都非常的重要.Java的IO机制也是一直在不断的完善,以 ...

随机推荐

  1. 在github上怎样克隆vue项目及运行

    长时间不做vue项目,今天看vue项目运行时有些指令忘记了,在这里写下相关指令 .克隆已有项目,一般情况项目中的README.md写的是项目运行步骤,一般项目的运行如下 克隆项目 git clone ...

  2. odoo中的QWeb模板引擎

    * 概述    QWeb是odoo主要模板引擎,采用xml表述,最后生成HTML文件    * 一般用法 #条件表达式 <t t-if="record.effort_estimate. ...

  3. Vim操作 -- 多段复位粘贴

    Vim可以多段复制.粘贴.即,内容X复制到寄存器“1”,内容Y复制到寄存器“2”:粘贴时可以选择从“1”还是“2”粘贴. (1) Vim有13个粘贴板,分别是0.1.2.....9.a.“.+:用:r ...

  4. 廖雪峰Java11多线程编程-3高级concurrent包-8CompletableFuture

    使用Future可以获得异步执行结果 Future<String> future = executor.submit(task); String result = future.get() ...

  5. where方法的用法是ThinkPHP查询语言的精髓

    where方法的用法是ThinkPHP查询语言的精髓,也是ThinkPHP ORM的重要组成部分和亮点所在,可以完成包括普通查询.表达式查询.快捷查询.区间查询.组合查询在内的查询操作.where方法 ...

  6. js实现iframe刷新

    今天要用到iframe的框架刷新,在网上找到了关于这方面内容,整理如下: (1)一般页面的刷新——reload 方法,该方法强迫浏览器刷新当前页面. 语法:location.reload([bForc ...

  7. JQValidate使用说明

    JQuery Validate使用总结:一.导入js库<script src="../js/jquery.js" type="text/javascript&quo ...

  8. c#设置文件及文件夹的属性

    c#中通过FileAttributes枚举来设置文件或文件夹的属性. FileAttributes 枚举 成员名称 说明 Archive 文件的存档状态.应用程序使用此属性为文件加上备份或移除标记. ...

  9. 05-4-style的代替操作

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. thymeleaf报错元素类型必须由匹配的结束标记终止

    spring boot 1.x 版本中thymeleaf报错元素类型 “link” 必须由匹配的结束标记 “</link>” 终止解决办法: 1.在pom.xml文件中添加: <de ...