Java NIO,bio编程 udp和tcp讲解

Tcp/udp协议

osi网络七层模型

为使不同计算机厂家的计算机能够互相通信,以便在更大的范围建立计算机网络,有必要建立一个国际范围的网络体系结构标准。具体其组成如下图:
Java NIO,bio编程 udp和tcp讲解
各层的主要功能:
物理层:使原始的数据比特流能在物理介质上传输。
数据链路层:通过校验、确认和反馈重发等手段,形成稳定的数据链路。
网络层:进行路由选择和流量控制。(IP协议)
传输层:提供可靠的端口到端口的数据传输服务(TCP/UDP协议)。
会话层:负责建立,管理和终止进程之间的会话和数据交换。
表示层:负责数据格式转换、数据加密与解密、压缩和解压缩等。
应用层:为用户的应用进程提供网络服务。

传输控制协议TCP
传输控制协议TCP是internet是一个重要的传输协议。TCP提供面向连接、可靠、有序、字节流传输服务。应用程序在使用TCP之前,必须建立TCP连接。
Java NIO,bio编程 udp和tcp讲解
TCP握手机制:
Java NIO,bio编程 udp和tcp讲解
3次握手可以发送数据 如: 1.跑过去跟女神说改天去吃饭 2,女神说可以 3,行某一天我们去吃饭
4次挥手 客户端说要结束了,服务端我已经收到可以等待(客户端等待不能发数据)
客户端延迟等待最后关闭
1.男:我们分手, 2女:既然你想分手就分手吧 3,女:但是是你要分手的不是我分手的 4,男:那分手吧
用户数据报协议udp
用户数据报协议UDP是Internet传输层协议。
提供无连接、不可靠、数据报尽力传输服务。
Java NIO,bio编程 udp和tcp讲解
udp和tcp的比较:
Tcp:面向连接、提供可靠性保证、慢、资源占用多
UDP:无连接、不可靠、快、资源占用少
Socket编程
Internet中应用最广泛的网络应用编程接口,实现与3种底层协议接口:
数据报类型套接字SOCK_DGRAM(面向UDP接口)
流式套接字SOCK_STREAM(面向TCP接口)
原始套接字SOCK_RAW(面向网络层协议接口ip、icmp等)
主要socket API及其调用过程
Java NIO,bio编程 udp和tcp讲解
Socket API函数定义
listen()、accept()函数只用于服务其端
connect()函数只能用于客户端;
socket()、bind()、send()、recv()、sendto()、recvfrom()、close()、

BIO网络编程:

http协议-请求数据包解析
Java NIO,bio编程 udp和tcp讲解
http协议-响应数据包解析
Java NIO,bio编程 udp和tcp讲解
http协议-响应状态码
1xx(临时响应)
表示临时响应并需要请求者继续执行操作的状态代码
2xx(成功)
表示成功处理了请求的状态代码。
3xx(重定向)
表示要完成请求,需要进一步操作。通常,这些状态码用来重定向。
4xx(请求错误)
这些状态码表示请求可能出错,妨碍了服务器的处理
5xx(服务器错误)
这些状态码表示服务其在尝试处理请求时发生内部错误。这些错误可能时服务器本身的错误,而不是请求出错。
BIO-阻塞io的含义
阻塞 io:资源不可用时,io请求一直阻塞,知道反馈结果(有数据或超时)
非阻塞 io:资源不可用时,io请求离开返回,返回数据标识资源不可用。
同步 io:应用阻塞在发送或接受数据的状态,知道数据成功传输或返回失败。
异步io:应用发送或接收数据后立刻返回,实际处理时异步执行的。
阻塞和非阻塞时获取资源的方式,同步/异步时程序如何处理资源的逻辑设计。代码中使用的API:serverSocket#INputStream#read都是阻塞的API。操作系统底层API中,默认Socket操作都是Blocking型,send/recv等接口都是阻塞的。
带来的问题:阻塞导致在处理网络i/o时,一个线程只能处理一个网络连接。
NIO网络编程
Java nio
始于java1.4 提供了新的JAVA IO 操作非阻塞API。用于替代java io和JAVAnetworking相关的api
nio有3个核心组件:Buffer缓冲区 Channel通道 Selector选择器

Buffer缓冲区

缓冲区本质上是一个可以写入数据的内存块(类似数组),然后可以再次读取。此内存块包含在NIO Buffer对象中,该对象提供了一组方法,可以更轻松地使用内存块。
使用Buffer进行数据写入与读取,需要进行如下四个步骤:
1、将数据写入缓冲区
2、调用buffer.flip(),转换为读取模式
3、缓冲区读取数据
4、调用buffer.clear()或buyffer.compact()清除缓冲区

Buffer工作原理
Buffer三个重要属性:
capacity:作为一个内存块,Buffer具有一定的固定大小,也称为“容量。
position位置:写入模式时代表写数据的位置。读取,模式时代表读取数据的位置。
limit限制:写入模式,限制等于buffer的容量。读取模式下,limit等于写入的数据量。
Java NIO,bio编程 udp和tcp讲解

ByteBuffer内存类型

ByteBuffer为性能关键型提供了直接内存(direct堆外)和非直接内存(head堆)两种实现。堆外内存获取的方式:ByteBuffer directByteBuffer=ByteBuffer.allocateDirect(noBytes)
好处:
1、进行网络io或者文件io时比headBuffer少一次拷贝。GC会移动对象内存,再写fie或socket的过程中,JVM的实现中,会先把数据复制到堆外,再进行写入。

2、GC范围之外,降低GC压力,但实现了的自动管理。DirectByteBuffer中有一个Cleaner对象
Cleaner会被GC前会执行clean方法,触发DirectByteBuffer中定义的Deadllocator
建议:
1、性能确实可观的时候才会去使用;分配给大型、长寿命;(网络传输、文件读写场景)
2、通过虚拟机参数MAxDirectMemorySize限制大小防止耗尽机器的内存;
堆外内存建议上
jvm写入时会多个步骤先是复制堆外内存在复制到jvm中原因是我们jvm在垃圾回收时候会移动内存地址操作系统会写入和读取可能读不到。堆外不受jvm管理,jdk有写
Channel通道:
Java NIO,bio编程 udp和tcp讲解
SocketChannel
SocketChannel用于建立TCP网络连接,类似java.net.Socket。有·两种创建socketChannel形式:
1.客户端主动发起和服务器的连接。
2、服务端获取的新连接。
Java NIO,bio编程 udp和tcp讲解
write写:write()在尚未写入任何内容时可能返回了。需要在循环中调用write().
read读:read()方法可能直接返回而根本不读取任何数据,根据返回的int值判断读取了多少字节。
Selector选择器
Selector是一个JAVA Nio组件,可以检查一个或多个NIO通道,并确定哪些通道已准备好进行读取或写入。实现单个线程可以管理多个通道,从而管理多个网络连接。

一个线程使用Selecttor监听多个channel的不同事件:
四个事件分别对应SelecttionKey四个常量。
1、Connect连接(SelectionKey.op_connect)
2、Accept准备就绪(op_ACCEPT)
3、read 读取(op_read)
4、Write写入(op_write)
Java NIO,bio编程 udp和tcp讲解
非阻塞的网络通道下,开发者通过Selector注册对通道感兴趣的事件类型,线程通过监听事件来非阻塞的网络通道下相应代码执行
Java NIO,bio编程 udp和tcp讲解

NIO对比BIO
Java NIO,bio编程 udp和tcp讲解
如果你的程序需要支撑大量的连接,使用NIO是最好的方式。
Tomcat8中,已经完全除去BIO相关的网络处理代码?默认采用NIO进行网络处理。
NIO与多线程结合的改进方案
Java NIO,bio编程 udp和tcp讲解
总结:
NIO为开发者提供了功能丰富及强大的io处理API,但是在应用中直接使用jdk停供的API比较繁琐而且要将性能进行提升关有NIO还不够,还需要将多线程技术与之结合起来。
因为网络编程本身的复杂性。以及jdkapi开发的使用难度较高,所以在开源社区中涌出来很多对jdk nio进行封装、增强后的网络编程框架,例如:Netty、Mina等。