Java网络通信编程基础

java 专栏收录该内容
6 篇文章 0 订阅

1、Socket

        Socket又称“套接字”,应用程序通过“套接字”向网络发出请求或者应答网络请求。

        Socket和ServerSocket类库位于java.net包中。ServerSocket用于服务器端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是平等的,不因为在服务器端或客户端而产生不同级别。不管是Socket还是ServerSocket,它们的工作都是通过SocketImpl类及其子类完成的。

 

2、Socket连接过程

        服务器监听:是服务端套接字,并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。

        客户端请求服务器:是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。

        服务器端连接确认:当服务器端套接字监听或者说接受到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,把服务端的套接字的描述发给客户端。

        客户端连接确认:一旦客户端确认了此描述,连接就建立好了,双方开始进行通信。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。

 

3、传统的BIO编程

        网络编程的基本模型是Client/Server模型,也就是两个进程直接进行相互通信,其中服务端提供配置信息(绑定的IP地址和监听端口),客户端通过连接操作向服务器端监听的地址发起连接请求,通过三次握手建立连接,如果连接成功,则双方即可以进行通信(网络套接字Socket)。(需要为每个连接维护一个线程)

 

4、伪异步IO

        采用线程池和任务队列可以实现一种伪异步的IO通信框架

        将客户端的socket封装成一个task任务(实现runnable接口的类),然后投递到线程池中去,配置相应的队列进行实现。

 

5、BIO、NIO、AIO的区别

        BIO为同步阻塞形式,NIO为同步非阻塞形式,NIO没有实现异步,在JDK1.7之后,升级了NIO库包,支持异步非阻塞通信模型,即NIO2.0(AIO)

        三种IO的总结:http://blog.csdn.net/wanzaixiaoxinjiayou/article/details/43274597

 

6、阻塞与非阻塞

        阻塞概念:应用程序在获取网络数据的时候,如果网络传输速度很慢,那么程序就一直等着,直到传输完毕为止。

        非阻塞概念:应用程序直接可以获取已经准备就绪的数据,无需等待。

        阻塞说的是具体的技术,接受数据的方式、状态(IO、NIO)

 

7、同步与异步

        同步:应用程序会直接参与IO读写操作,并且我们的应用程序会直接阻塞到某一个方法上,直到数据准备就绪;或者采用轮询的策略实时检查数据的就绪状态,如果就绪则获取数据。

        异步:所有的IO读写操作交给操作系统处理,与我们的应用程序没有直接关系,我们程序不需要关系IO读写,当操作系统完成了IO读写操作时,会给我们应用程序发送通知,我们应用程序直接拿走数据即可。

        同步与异步的区别:同步和异步一般是面向操作系统与应用程序对IO操作的层面上来区别的。

        

8、NIO相关概念

        NIO的本质就是避免原始的TCP建立连接使用3次握手的操作,减少连接的开销。

        Buffer(缓冲区)、Channel(管道、通道)、Selector(选择器、多路复用器)

        创建一个Selector相当于一个观察者打开一个Server端通道,把这个Server通道注册到观察者上并且指定监听事件,然后遍历这个观察者观察到的事件,取出感兴趣的事件再出来。这里有个最核心的地方就是,我们不需要为每个被观察者创建一个线程来监控它随时发生的事件,而是把这些被观察者都注册一个地方统一管理,再由它把触发的事件统一发送给感兴趣的程序模块。这里的核心是能够统一的管理每个被观察者的事件,所以我们就可以把服务端的每个建立的连接传送和接受数据作为一个事件统一管理,这样就不必每个连接需要一个线程来维护了。

 

9、Buffer(缓冲区)

        Buffer是一个对象,它包含一些要写入或者要读取的数据。在NIO类库中加入Buffer对象,体现了现库与原IO一个重要的区别。在面向流的IO中,可以将数据直接写入或读取到Stream对象中。在NIO库中,所有数据都是用缓冲区处理的(读写)。缓冲区实质上也是一个数组,通常它是一个字节数组(ByteBuffer),也可以使用其他类型的数组。这个数组为缓冲区提供了数据的访问读写等操作属性,如位置、容量、上限等概念,参考api文档。

        Buffer类型:我们最常用的就是ByteBuffer,实际上每一种java基本类型都对应了一种缓冲区(Boolean类型除外)。(ByteBuffer、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer)

        NIO之Buffer的clear()、rewind()、flip()方法的区别:http://blog.csdn.net/wanzaixiaoxinjiayou/article/details/43274597

 

10、Channel(通道)

        Channel就像自来水管道一样,网络数据通过Channel读取和写入,通道与流不同之处在于通道是双向的,而流只是一个方向上移动(一个流必须是InputStream或者OutputStream的子类),而通道可以用于读、写或者二者同时进行,最关键的是可以与多路复用器结合起来,有多种状态位,方便多路复用器识别。事实上通道分为两大类,一类是网络读写的(SelectableChannel),一类是用于文件操作的(FileChannel),我们使用的SocketChannel和ServerSocketChannel都是SelectableChannel的子类。

 

11、Selector

        多路复用器(Selector),他是NIO编程的基础,非常重要。多路复用器提供选择已经就绪的任务的能力。

        简单说,就是Selector会不断地轮询注册在期上的通道(Channel),如果某个通道发生了读写操作,这个通道就处于就绪状态,会被Selector轮询出来,然后通过SelectionKey可以取得就绪的Channel集合,从而进行后续的IO操作。

        一个多路复用器(Selector)可以负责成千上万Channel通道,没有上限。这也是JDK使用了epoll代替了传统的select实现,获得连接句柄没有限制。这也就意味着我们只要一个线程负责Selector的轮询,就可以接入成千上万个客户端,这是JDK NIO库巨大的进步。

        Selector线程类似一个管理者(Master),管理了成千上万个通道,然后轮询哪个管道的数据已经准备好,通知cpu执行IO的读取或写入操作。

        Selector模式:当IO事件(管道)注册到选择器以后,Selector会分配给每个管道一个key值,相当于标签。Selector选择器是以轮询的方式进行查找注册的所有IO事件(管道),当我们的IO事件(管道)准备就绪后,select就会识别,会通过key值来找到相应的管道,进行相关的数据处理操作(从管道里读或写数据,写到我们的缓存缓冲区中)。

        每个管道都会对选择器进行注册不同的事件状态,以便选择查找。(SelectionKey.OP_CONNECT、SelectionKey.OP_ACCEPT、SelectionKey.OP_READ、SelectionKey.OP_WRITE)

 

12、AIO

        AIO,在NIP基础之上引入了异步通道的概念,并提供了异步文件和异步套接字通道的实现,从而在真正意义上实现了异步非阻塞,NIO只是非阻塞而并非异步。而AIO它不需要通过多路复用器对注册的通道进行轮询操作即可实现异步非读写,从而简化了NIO编程模型。也可以称之为NIO2.0,这种模式才真正的属于我们异步非阻塞的模型。(AsynchronusServerSocketChannel、AsynchronousSocketChannel)

 

13、Netty简介

        Netty是基于Java NIO的网络应用框架。Netty是一个NIO client-server(客户端服务器)框架,使用Netty可以快速开发网络应用,例如服务器和客户端协议。Netty提供了一种新的方式来开发网络应用程序,这种新的方式使得它很容易使用和很强的扩展性。Netty的内部实现是很复杂的,但是Netty提供了简单易用的api从网络处理代码中解耦业务逻辑。Netty是完全基于NIO实现的,所以整个Netty都是异步的。

        网络应用程序通常需要较高的可扩展性,无论是Netty还是其他的基于Java NIO的框架,都会提供可扩展性的解决方案。Netty中一个关键组成部分是它的异步特性。

        Netty是最流行的NIO框架,他的健壮性、功能、性能、可定制性和可扩展性在同类框架里都是首屈一指的。它已经得到成百上千的商业/商用项目验证。

 

14、Netty实现通信的步骤

        创建两个NIO线程组,(IO多路复用模型),一个专门用于网络事件处理(接受客户端的连接),另一个则进行网络通信读写。

        创建一个ServerBootstrap对象,配置Netty的一系列参数,例如接受传出数据的缓存大小等等。

        创建一个实际处理数据的类ChannelInitializer,进行初始化的准备工作,比如设置接受传出数据的字符集、格式、以及实际处理数据的接口。

        绑定端口,执行同步阻塞方法等待服务器启动即可。

        http://ifeve.com/netty5-user-guide/

 

15、TCP粘包、拆包问题

        无论是服务器端还是客户端,当我们读取或者发送数据的时候,都需要考虑TCP底层的粘包/拆包机制。

        TCP是一个“流”协议,所谓流就是没有界限的遗传数据。可以想象下如果河里的水就好比数据,它们是连成一片的,没有分界线,TCP底层并不了解上层业务的具体的含义,他会根据TCP缓冲区的实际情况进行包的划分,也就是说,在业务上,我们一个完整的包可能会被TCP分成多个包进行发送,也可能把多个小包封装成一个大的数据包发送出来,这就是所谓的TCP粘包、拆包问题。

 

16、TCP粘包、拆包问题的产生原因

        应用程序write写入的字节大小大于套接口发送缓冲区的大小

        进行MSS大小的TCP分段

        以太网帧的payload大于MTU进行IP分片

 

17、拆包、粘包问题的解决方案

        消息定长,例如每个报文的大小固定为200个字节,如果不够空位补空格;

        在包尾部增加特殊字符进行分割。例如加回车等级。

        讲消息分为消息头和消息体,在消息头中包含表示消息总长度的字段,然后进行业务逻辑的处理。

 

18、Netty编解码技术

        编解码技术,说白了就是java序列化技术,序列化的目的就两个,第一进行网络传输,第二持久化。

        虽然可以使用java进行对象序列化,netty去传输,但是java序列化的硬伤太多,比如java序列化没法跨语言、序列化后码流太大、序列化性能太低等等

        主流的编解码框架:JBoss的Marshaling包,google的Protobuf、基于Protobuf的Kyro、MessagePack框架

 

19、数据通信

        第一种:使用长连接通道不断开的形式进行通信,也就是服务器和客户端的通道一直处于开启状态,如果服务器性能足够好,并且客户端数量也比较少的情况下,还是推荐这种的。

        第二种:一次性批量提交数据,采用短连接方式。也就是我们会把数据保存在本地临时缓冲区或者临时表里,当达到临界值时进行一次批量提交,又或者根据定时任务查询提交,这种情况弊端是做不到实时性传输,在对实时性不高的应用程序中可以推荐使用。

        第三种:我们可以用一种特殊的长连接,在指定某一段时间内,服务器与某台客户端没有通信,则断开连接。下次连接则是客户端向服务器发送请求的时候,再次建立连接,但是这种模式我们需要考虑两个因素:①如何在超时(即服务器与客户端没有任何通信)后关闭通道?关闭通道后我们又如何再次建立连接?②客户端宕机时,我们无需考虑,下次客户端重启之后就可以与服务器建立连接,但是服务器宕机时,我们的客户端如何与服务器进行连接呢?

 

20、心跳监控

        使用Socket通信一般经常会处理多个服务器之间的心跳检测。一般来讲我们去维护服务器集群,肯定要有一台或几台服务器主机(Master),然后还应该有N台(Slave),那么我们的主机肯定要时时刻刻知道自己下面的从服务器的各方面情况,然后进行实时监控的功能,这个分布式架构里叫心跳监控。处理方案可以使用一些通信框架进行实现,Netty就可以去做这样一件事。

        可以用sigar jar包获取机器状态信息

 

21、HTTP协议

        HTTP(超文本传输协议)是建立在TCP传输协议之上的应用层协议,它目前主流是针对于web开发,HTTP协议应用非常广泛,因此掌握HTTP协议的开发非常重要。使用Netty的Http协议也是异步非阻塞的。

 

22、HTTP协议特点

        简单:客户端请求服务器时只要指定UPL和携带必要的参数即可。

        灵活:HTTP协议允许传输任意类型的数据对象,传输内容HTTP头中的Content-Type加以标记。

        无状态:HTTP协议是无状态的,无状态指的是协议对事物处理没有记忆能力。这意味着如果

后续处理需要之前的信息,则它必须重新获取。也从侧面体系HTTP协议的设计是为了使网络传输更加的轻量级、敏捷、负载较轻。

 

23、HTTP协议组成部分

        请求行、请求头、请求正文(实体内容)

 

24、Netty HTTP文件服务端开发

        Netty的HTTP协议栈无论从性能上还是可靠性上都表现优异,非常适合web场景下运用,相比于传统的Tomcat、Jetty等Web容器,他更加的轻量和小巧,灵活性和定制性也更好

  • 0
    点赞
  • 0
    评论
  • 4
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值