一、前言

为什么要学Netty?

  实话说工作中真正用到netty开发的场景可能不算特别多,但是为啥要学这玩意呢?有一说一,变强的路上技能可以用不到,但是不能没有~

  Java生态圈内的大量开源框架比如Dubbo、Zookeeper等等都用到了Netty,如果我们想去看源码,看完下来又不懂netty是啥,那不就麻了,对未知心怀畏惧但又跃跃欲试,废话不多说,直接卷起来。

  跟着课程慢慢学,一步一步来吃掉它。

二、网络协议

  作为一套网络通信框架,如果不了解网络相关的基础知识,那学起来也是听天书一样,先简单回顾一下网络协议相关的知识点,加深印象。

计算机网络是什么?

  定义:利用通信线路将地理上分散的、具有独立功能的计算机系统和通信设备按不同的形式连接起来,以功能完善的网络软件及协议实现资源共享和信息传递的系统。

  简单概括:将地理上分散的计算机连接起来并互相可以进行信息传递的系统。

  分类:

局域网【LAN】:几米~几十公里城域网【MAN】:介于LAN和WAN之间广域网【WAN】:几十~几千公里

  设计初衷:战争环境下构造一个分散的指挥系统,当部分指挥点被摧毁后,其它点仍能正常工作,并且在这些点之间能够绕过那些已被摧毁的指挥点而继续保持联系。

计算机网络体系结构?

  计算机网络体系结构中,最核心的知识点就是OSI七层模型,TCP/IP五层模型,以及TCP/IP协议族了,我们一起分析下这几个知识点就是是啥?

OSI七层模型

  简称:开放系统互连参考模型。

  制定机构:国际标准化组织(ISO)和国际电报电话咨询委员会(CCITT)联合制定。

  设计初衷:为各种计算机互连提供一个共同的基础和标准框架,并为保持相关标准的一致性和兼容性提供共同的参考。【制定不同计算机互联之间的规范和规则】

  分层图解:

TCP/IP模型

  简称:TCP/IP5层模型、TCP/IP4层模型。【将物理层、数据链路层合称为网络接口层】

  制定机构:电气与电子工程师协会(IEEE)

  设计初衷:在OSI七层模型的基础上设计一套更贴合设计开发的分层模型。

  分层图解:

TCP/IP协议族

  简称:传输控制协议/因特网互联协议。

  设计初衷:是Internet最基本的协议、Internet国际互联网络的基础。

  PS:它其实是个协议家族,由很多个协议组成, 并且是在不同的层, 是互联网的基础通信架构。

  分层图解:

IP、TCP和UDP协议

IP【网际协议】

  定义:用来确定网络中唯一的一台计算设备。

  主要职责:对数据加上IP地址和其他的数据以确定传输的目标。

  工作位置:网络层

TCP【传输控制协议】

  定义:面向连接的,可靠的数据传输协议。

  特点:重传和确认【所以相对UDP传输速度会慢一些】

  主要职责:对数据加上IP地址和其他的数据以确定传输的目标。

  工作位置:传输层

UDP【用户数据报协议】

  定义:无需建立连接就可以发送数据的传输协议。

  特点:不可靠【没有确认和重传机制,所以相对TCP传输速度会快一些】

  主要职责:不用建立连接直接向用户传输数据。

  工作位置:传输层

三、TCP/IP 网络传输中的数据

  每个分层中,都会对所发送的数据附加一个首部,在这个首部中包含了该层必要的信息,如发送的目标地址以及协议相关信息。通常,为协议提供的信息为包首部,所要发送的内容为数据。在下一层的角度看,从上一层收到的包全部都被认为是本层的数据。

  PS:网络中传输的数据包由两部分组成:

协议所要用到的首部上一层传过来的数据

  首部的结构由协议的具体规范详细定义。在数据包的首部,明确标明了协议应该如何读取数据。反过来说,看到首部,也就能够了解该协议必要的信息以及所要处理的数据。

  通过一个图例说明:

① 用户A应用程序处理。首先应用程序会进行编码处理产生报文/消息(message)交给下面的TCP层。② 用户A的TCP模块的处理。TCP根据应用的指示,负责建立连接、发送数据以及断开连接。TCP需要将应用层数据封装为报文段 (segment)并附加一个TCP首部然后交给下面的IP层。③ 用户A的IP模块的处理。IP将TCP传过来的TCP首部和TCP数据合起来当做自己的数据,并在TCP首部的前端加上自己的IP首部生成IP数据报(datagram)然后交给下面的数据链路层。④ 用户A数据链路层的处理。从 IP 传过来的 IP 包对于数据链路层来说就是数据。给这些数据附加上链路层首部封装为链路层帧(frame),生成的链路层帧(frame)将通过物理层传输给接收端。⑤ 用户B数据链路层的处理。用户B主机收到链路层帧(frame)后,首先从链路层帧(frame)首部找到MAC地址判断是否为发送给自己的包,若不是则丢弃数据。 如果是发送给自己的包,则从以太网包首部中的类型确定数据类型,再传给相应的模块,如 IP、ARP 等。⑥ 用户B的IP模块的处理。IP模块接收到数据后也做类似的处理。从包首部中判断此IP地址是否与自己的IP 地址匹配,如果匹配则根据首部的协议类型将数据发送给对应的模块,如 TCP、UDP。⑦ 用户B的TCP模块的处理。在TCP模块中,首先会计算一下校验和,判断数据是否被破坏。然后检查是否在按照序号接收数据。最后检查端口号,确定具体的应用程序。数据被完整地接收以后,会传给由端口号识别的应用程序。⑧ 用户B应用程序的处理。接收端应用程序会直接接收发送端发送的数据。通过解析数据,展示相应的内容。

  PS:3次握手一定是客户端发起的,但4次分手有可能是服务端发起!

四、地址和端口号

MAC地址

  定义:媒体访问控制地址【局域网地址(LAN Address)】

  生成时机:由网络设备制造商生产时写在硬件内部。

  PS:MAC地址与网络无关,即无论将带有这个地址的硬件(如网卡、集线器、 路由器等)接入到网络的何处,都有相同的 MAC 地址,它由厂商写在网卡的BIOS里,从理论上讲,除非盗来硬件(网卡),否则是没有办法冒名顶替的。

  组成:MAC地址共48位(6 个字节)。

前24位由IEEE(电气和电子工程师协会)决定如何分配。后24位由实际生产该网络设备的厂商自行制定。每个字节由2个16进制数来进行展示。例如:FF:FF:FF:FF:FF:FF 或 FF-FF-FF-FF-FF-FF

IP地址

  定义:互联网协议地址【为互联网上的每一个网络和每一台主机配置一个唯一的逻辑地址,用来与物理地址作区分。】

  组成IPv4:32位的二进制数(4个字节)例如:127.0.0.1【4个8位二进制数】

IP地址和MAC地址之间的区别【重点】

  1、IP地址的设计是出于拓扑设计出来的,只要在不重复 IP 地址的情况下,它是可以随意更改的;而MAC地址是根据生产厂商烧录好的,它一般不能改动的,当一台PC机的网卡坏了之后,更换了网卡之后MAC地址就会变了。

  2、长度不同,IP地址的长度为32位,而MAC地址为48位。

  3、它们的寻址协议层不同。IP地址应用于OSI模型的网络层,而MAC地址应用在OSI 模型的数据链路层。 数据链路层协议可以使数据从一个节点传递到相同链路的另一个节点上(通过MAC地址),而网络层协议使数据可以从一个网络传递到另一个网络上(ARP根据目的IP地址,找到中间节点的MAC地址,通过中间节点传送,从而最终到达目的网络)。

  4、分配依据不同。IP地址的分配是基于我们自身定义的网络拓扑,MAC地址的分配是基于制造商。

端口号【程序地址】

  作用:识别同一台计算机中进行通信的不同应用程序。

  意义:一台计算机上同时可以运行多个程序。传输层协议正是利用这些端口号识别本机中正在进行通信的应用程序,并准确地将数据传输。

  数量:65535个

为什么端口有65535个?

  在TCP、UDP协议报文的开头,会分别有16位二进制来存储源端口号和目标端口号,所以端口个数是 2^16=65536 个,但是0号端口用来表示所有端口,所以实际可用的端口号是65535个。

端口号是如何确定下来的?

(1)标准既定的端口号

  含义:每个应用程序都有其指定的端口号。

  PS:分布在0~1023之间的端口是针对特定应用协议制定的,为知名端口号,我们在编写自己的网络应用服务时,尽量不要使用这些端口号。

(2)时序分配法

  含义:操作系统全权进行动态分配端口号。

  PS:操作系统分配的端口号一般都是大于10000的。

如何观察端口号?

(1)windows系统 

-- 1、查看所有端口

netstat -ano

-- 2、查看指定端口

netstat -ano|findstr 端口号

(2)linux系统

-- 1、查看指定端口

lsof -i:端口号

五、网络通信五元组

  组成:

1、源IP地址2、目标IP地址3、协议号(协议类型)4、源端口号5、目标端口号

  PS:操作系统是通过源IP地址、目标IP地址、协议号(协议类型)、源端口号、目标端口号这五个元素唯一性的识别一个网络上的通信。

六、详解TCP

TCP特性【重点】

  关键字:可靠、超时/丢包重传、应答确认、数据拆分、排序、三次握手、四次挥手

三次握手【重点】

  含义:TCP提供面向有连接的通信传输。面向有连接是指在数据通信开始之前先做好两端之间的准备工作。

  解析:指建立一个TCP连接时需要客户端和服务器端总共发送三个包以确认连接的建立。【发起连接的一方我们称为客户端,接收连接的一方我们称之为服务端】

  第一次握手:客户端将请求报文标志位SYN置为 1,请求报文的SequenceNumber字段 (简称 seq)中填入一个随机值J,并将该数据包发送给服务器端,客户端进入SYN_SENT状态,等待服务器端确认。

  第二次握手:服务器端收到数据包后由请求报文标志位SYN=1知道客户端请求建立连接,服务器端将应答报文标志位SYN和ACK都置为1,应答报文的AcknowledgmentNumber字段(简称 ack)中填入 ack=J+1,应答报文的seq中填入一个随机值K,并将该数据包发送给客户端以确认连接请求,服务器端进入SYN_RCVD状态。

  第三次握手:客户端收到应答报文后,检查ack是否为J+1,ACK是否为1,如果正确则将第三个报文标志位ACK置为1,ack=K+1,并将该数据包发送给服务器端,服务器端检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,客户端和服务器端进入ESTABLISHED状态,完成三次握手,随后客户端与服务器端之间可以开始传输数据了。

为什么TCP握手需要三次?【重点】

  优势:三次握手是保证数据可靠传输又能提高传输效率的最小次数。

  原因:

1、通信双方相互告知序列号起始值,并确认对方已经收到了序列号起始值的必经步骤。2、若只是两次握手, 至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认。【服务端不知道消息发出并被接收成功了】3、至于为什么不是四次,是因为三次握手后,通信的双方都已经知道了对方序列号起始值,也确认了对方知道自己序列号起始值,第四次握手已经毫无必要了。

TCP三次握手的漏洞-SYN洪泛攻击

  背景:三次握手中有一个第二次握手,服务端向客户端应答请求,应答请求是需要客户端IP的,而且因为握手过程没有完成,操作系统使用队列维持这个状态。

  起因:攻击者就伪造这个 IP,往服务器端狂发送第一次握手的内容,当然第一次握手中的客户端IP地址是伪造的,从而服务端忙于进行第二次握手,但是第二次握手是不会有应答的,所以导致服务器队列满,而拒绝连接。

  解决方案:无效连接监视释放、延缓TCB分配方法、防火墙(推荐)【防火墙原理:确认了连接的有效性后,才向内部的服务器发起 SYN 请求】

四次挥手【重点】

  含义:断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。

  PS:由于TCP连接是全双工的,因此每个方向都必须要单独进行关闭。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。

  1、某个应用进程执行主动关闭,该端的TCP发送一个FIN分节,表示数据发送完毕,应用进程进入FIN-WAIT-1【终止等待1】状态。

  2、接收到这个FIN的对端执行被动关闭,并发出确认报文。接收端进入了CLOSE-WAIT【关闭等待】状态,即主动关闭端已经没有数据要发送了,但是被动关闭端若发送数据,主动关闭端依然要接受。主动关闭端收到确认报文后进入FIN-WAIT-2【终止等待2】状态。

  3、一段时间后,被动关闭的应用进程将关闭它的套接字。这导致它的TCP也发送一个FIN,表示它也没数据需要发送了。

  4、接收这个最终FIN的原发送端TCP【即执行主动关闭的那一端】,发出一个用于确认的ACK报文,并进入了TIME-WAIT【时间等待】状态。

    PS:此时TCP连接还没有释放,必须经过2∗MSL【最长报文段寿命/最长分节生命期,指IP数据报能够在因特网中存活的最长时间,任何TCP实现都必须为MSL选择一个值。】【1MSL一般30s~2min】

  5、被动关闭端只要收到了客户端发出的确认,立即进入CLOSED【关闭】状态。

    PS:被动关闭端结束TCP连接的时间要比主动关闭端早一些。 

    PS:MSL是由协议本身规定的。

为什么TCP的挥手需要四次?【重点】

  TCP是全双工的连接,必须两端同时关闭连接,连接才算真正关闭。

(1)主动关闭方已经准备关闭写,发送FIN,但是它还可以读另一方发送的数据。(2)被动关闭方收到FIN后,回复ACK报文。(3)当被动关闭方也已经写完了准备关闭,发送 FIN 报文。(4)主动关闭方回复ACK。两端都关闭,TCP 连接正常关闭。

为什么需要TIME-WAIT状态?【重点】

  原因:

1、可靠地终止TCP连接。2、保证让迟来的TCP报文有足够的时间被识别并丢弃。

  根据前面的四次握手的描述,我们知道,客户端收到服务器的连接释放的FIN报文后,必须发出确认。如最后这个ACK确认报文丢失,那么服务器没有收到这个ACK确认报文, 就要重发FIN连接释放报文,客户端要在某个状态等待这个FIN连接释放报文段然后回复确认报文段,这样才能可靠的终止TCP连接。

  在Linux系统上,一个TCP端口不能被同时打开多次,当一个TCP连接处于TIME_WAIT状态时,我们无法使用该链接的端口来建立一个新连接。反过来思考,如果不存在TIME_WAIT状态,则应用程序能过立即建立一个和刚关闭的连接相似的连接(指他们具有相同的IP地址和端口号)。这个新的、和原来相似的连接被称为原来连接的化身。新的化身可能收到属于原来连接的服务端发回的数据TCP报文段(迟到的报文段),这显然是不该发生的。这是TIME_WAIT状态存在的第二个原因。

  PS:大量的TIME_WAIT状态有可能是因为客户端程序代码中没有主动关闭链接,导致服务器端一直等待,直到MSL时间后才由服务端主动关闭链接。

好文阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: