传统的java自带的socket每次创建链接都会创建一个新的线程。建立线程过度的浪费服务器系统资源。java
jdk1.5前没有NIO时经过伪异步方式解决,用线程池解决问题。缓存
IO和NIO的本质区别:阻塞和非阻塞的区别服务器
阻塞:应用程序中获取网络数据的时候,若是网络传输数据很慢,那么程序就一直等着,直到传输完毕为止。网络
非阻塞:应用程序直接能够获取已经准备好的数据,无需等待。异步
BIO为同步阻塞形式,NIO为异步非阻塞形式。NIO并无实现异步,中jdk1.7以后升级了NIO库包。socket
同步和异步:同步和异步通常是面向操做系统与应用程序对IO操做的层面上来区别的。ide
同步时,应用程序会直接参与IO操做,而且咱们的应用程序会直接阻塞到某个方法上,直到数据准备就绪;或者采起轮询的策略实时检查数据的就绪状态,若是就绪则获取数据。ui
异步时,则全部的IO读写操做交给操做系统处理,与咱们的应用程序没有直接关系,咱们的程序不关心IO读写,当操做系统完成了IO读写操做时,会给咱们应用程序发通知,咱们的应用程序直接拿走数据便可。操作系统
同步说的是server服务器端端执行方式。线程
阻塞说的是具体技术,接受数据的方式、状态(IO,NIO)
AIO
Asynchronous Input/Output异步输入/输出是任何特殊输入/输出流
异步输入/输出是任何特殊输入/输出流(同步和异步输入/输出)两个基本操做模式之一。在异步模式中,天然的输入/输出事务没必要须和一个程序的输入/输出状态同步或互锁。例如,一个用户或一个打字员应该被容许将信息提早输入系统中来执行可以使用它们的读状态。每一个读状态的执行仅仅将下一个等待信息从一个输入缓冲器中去除。这个异步输入的例子相似于已经用于唱片、磁带等中的缓冲提早读方案。
Netty
netty实现通讯:
1 建立两个NIO线程组,一个专门用于网络事件处理(接受客户端的链接),另外一个则进行网络通讯编写。
2 建立一个ServerBootstrap对象,配置netty的一系列参数,例如接受传出数据的缓存大小等等。
3 建立一个世纪处理数据的类ChannelInitializer,进行初始化的准备工做,好比设置接受传出数据的字符集、格式、已经实际处理数据的接口。
4 绑定端口,执行同步阻塞方法等待服务器端启动便可。
示例:http://ifeve.com/netty5-user-guide/ 翻译很差,可是例子比较简单全面。
TCP粘包拆包问题
TCP是一个流协议。所谓流就是没有界限的遗传数据。你们能够想象为若是河水就比如数据,他们是连成一片的,没有分界线。TCP底层并不了解上层的业务数据具体的含义,它会根据TCP缓冲区的实际状况进行报的划分,也就是说,在业务上咱们一个完整的报可能会被TCP分红多个包进行发送,也可能把多个小包封装成一个大的数据包发送出去,这就是所谓的TCP拆包粘包问题。
分析TCP粘包拆包问题产生缘由:
1应用程序write写入的字节大小大于套接口发送缓冲区的大小。
2进行MSS大小的TCP分段。
3以太网帧的payload大雨MTU进行IP分片。
三种方案:
1消息定长,例如每一个报文的大小固定为200个字节,若是不够,空位补空格。
2在包尾部增长特殊字符进行分割。
3将消息分为消息头和消息体,在消息头中包含消息总长度的字段,而后进行业务逻辑的处理。
netty中解决方法:
1 分隔符类 DelimiterBasedFrameDecoder(自定义分隔符)
2FixedLengthFrameDecoder(定长)