码出高效读书笔记:TCP/IP

1.网络协议

TCP/IP中文译名为传输控制协议/因特网互联协议。

这个大家族里的其他知名协议还有HTTP、HTTPS、FTP、SMTP、UDP、ARP、IEEE802.x等。

TCP/IP是当前流行的网络传输协议框架,从严格意义上来讲它是一个协议族,因为TCP和IP协议是其中最为核心的协议,所以就将该协议族成为TCP/IP。这个协议族是一个四层模型,包括:Application(应用层)、Transport(传输层)、Internet(网络层)、Link(链路层)。TCP处于Transport,而IP处于Internet。

另一个耳熟能详的ISO/OSI七层传输协议已经被淘汰。

TCP/IP与OSI模型对照图如下图所示:

上文中提到TCP/IP分为四层,分别是应用层、传输层、网络层、链路层,下图为数据从机器A到机器B的整个流程以及每层所涉及的协议:

  • 链路层:单个0和1是没有意义的,链路层以字节为单位把0和1进行分组,定义数据帧,写入源和目标机器的物理地址、数据、校验位来传输数据(FSC为校验位),下图为数据帧的结构

    MAC地址长6个字节共48位,前24位管理机构同一分配,后24位由厂商自己分配,作用是保证网卡全球唯一。

  • 网络层:根据IP定义网络地址,区分网段。子网内根据地址解析协议ARP进行MAC寻址,子网外进行路由转发数据包,这个数据包就是IP数据包。ARP协议:主机发送信息时,将包含目标IP地址的ARP请求广播到当前网络上的所有主机,并接收回复消息,以确定目标IP主机的MAC地址。

    扫描二维码关注公众号,回复: 4942016 查看本文章
  • 传输层:数据包通过网络层发送到目标计算机后,应用程序在传输层定义逻辑端口(每一个应用程序对应一个端口号),确认身份后,将数据包从对应的端口交给应用程序,实现端口到端口之间的通信,传输层最典型的协议就是UDP、TCP协议。UDP是面向无连接的,是不可靠传输,多用于视频,优点是连接快,缺点是不能保证所有数据都传输到目的地。TCP是面向连接的,是一种端到端之间通过失败重传机制建立的可靠传输方式。

  • 应用层:传输层的数据到达应用程序时,以某种统一规定的协议格式解读数据。比如E-mail在各个公司的程序界面、操作、管理方式都不相同,但是都可以解读邮件的内容,那是应为SMTP协议能按照规定来填写和解读收信人、信件内容等信息。

总结一下数据打包传递的过程:

简而言之就是按照“端口--->IP地址--->MAC地址”这样的路径进行数据的封装和发送。数据到达B机器时,再反过来操作对数据进行解包,最后让应用程序接收数据。

2.IP协议

IP是面向无连接、无状态的,没有额外的机制保证数据包能有序到达。

IP地址属于网络层,主要功能在WLAN内进行路由寻址,选择最佳路由。IP地址长度共32位4个字节,通常使用十进制来表示。

IP数据报格式如下图所示:

重点:数据包的生存时间(TTL----->Time to Live),该字段表示IP报文被路由器丢弃之前可经过的最多路由总数。TTL初始值由源主机设置后,数据包在传输过程中每经过一个路由器TTL值减一,当该字段为0时,该数据包被丢弃,并发送ICMP报文通知源主机,以防止源主机无休止的发送报文。

ICMP(Internet Control Message Protocol)互联网控制报文协议:作用是检测传输网络是否通畅、主机是否可达、路由是否可用等网络运行状态的协议。ICMP虽然不传输用户数据,但是对评估网络健康状态非常重要,经常使用的ping、tracert命令就是基于ICMP检测网络状态的有力工具。

3.TCP建立连接

TCP(Transmission Control Protocol)传输控制协议:是一种面向连接、确保数据在端到端之间可靠传输的协议。

面向连接是指在发送数据前,要先建立一条虚拟的链路,然后让数据在这条链路上流动从而完成传输。

为了保证数据的可靠传输,不仅需要对发出的每一个字节进行编号确认,校验每一个数据包的有效性,在出现超时情况时重传,还需要通过实现滑动窗口拥塞控制等机制,避免网络状况恶化而最终影响数据传输的极端情况。

每个TCP数据包是封装在IP包中的,每一个IP头的后面紧接着的是TCP头。TCP报文格式如下图所示:

第一行不必多说,是源机器和目标机器的端口号,这两个端口号与IP报头中的源IP地址和目标IP地址所组成的四元组可唯一标识一条TCP连接。如下图所示

由于TCP是面向连接的,所以有客户端和服务端之分,需要服务器先在相应的端口上进行监听,准备好接收客户端发起的建立连接请求。当客户端发起第一条建立连接的TCP包时,目标机器端口就是服务端所监听的端口号。例如一些广为人知的端口号,HTTP服务的80端口,HTTPS服务的443端口,SSH服务的22端口等。

第二行和第三行是序列号,各占4个字节。前者是指所发送数据包中数据部分第一字节的序号,后者是指期望受到来自对方的下一个数据包中数据部分的第一字节的序号。

TCP的FLAG位由6个bit组成,分别代表SYN、ACK、FIN、URG、PSH、RST,都以置1表示有效。我们重点关注标为红字的SYN、ACK、FIN这三个FLAG。

SYN(Synchronize Sequence Numbers)用作建立连接时的同步信号;

ACK(Acknowledgement)用于对收到的数据进行确认,所确认的数据由确认序列号表示;

FIN(Finish)表示后面没有数据需要发送,通常意味着建立的连接需要关闭了。

TCP三次握手

三次握手指的是建立连接的三个步骤:

  1. 客户端发出一个数据包并将SYN置为1,表示希望建立连接,包中的序列号seq是随机生成的一个数x。
  2. 服务端收到客户端发来的数据包,通过SYN的状态值知道这是要建立一条连接的请求,于是发送一个响应数据包给客户端,并将SYN和ACK置为1,随机生成一个序列号seq为y,而确认序列号ack为x+1,表示是响应客户端发来的的序列号为x的连接请求。在TCP中,SYN被当做是数据部分的一个字节。
  3. 客户端收到服务端发来的响应包数据后,在发给服务端的确认包中将ACK置为1,并将序列号seq设置为x+1,将确认序列号设置为y+1,表示收到了来自服务端的SYN。

Q:为什么需要第三次握手呢?

A:有两个原因:

  1. 第二次握手以后,服务端还不能确认自己的发报能力以及客户端的收报能力,要通过第三次握手来确定这两项能力是正常的,如下表所示

  2. 为了防止客户端已经失效的连接请求又“莫名其妙”的到达了服务端,服务端接收了这个已经失效的连接请求,而与客户端建立多余的连接通道,导致服务端资源被浪费。              假设客户端A第一次发送了一个建立连接的请求包1,这个请求包1并没有丢失,而是在某些网络节点上滞留了很长的时间,而A认为长时间没有收到服务端B发来的响应包1是因为请求包1丢失了,于是发送建立连接的请求包2,这一次2很快被服务端B响应了,于是A和B建立了连接,双方开始双向数据传输。但是过了一段时间以后,这个在网络节点上滞留了很长时间的请求包1被送到了服务端B,而B并不知道这个请求包1已经被A判定为丢失,于是按照正常的约定,又响应了这个请求包1,并发送响应数据包1给客户端,但是客户端对于这个通过请求包1建立的连接通道1并不买账,于是还是继续通过前面请求包2建立的连接通道2发送数据,但是在服务端那里连接通道1是正常的,所以还会保留这个连接通道1,但是这个连接通道1并没有起到任何作用,于是白白的浪费了服务端B的许多资源。    所以要通过第三次握手,让客户端A不理会这个B发来的响应包1,不发送确认包给B,从而禁止A和B建立连接通道1。

TCP三次握手过程如下图所示:

TCP的四次挥手

TCP是全双工通信,双方都可以作为数据的发送方和接收方。所谓相爱容易分手难,建立连接只有3次,但是挥手断开就有4次,主要是如下四个步骤:

  1. 客户端A想要关闭连接,则等待本方数据发送完毕后,传递FIN=1信号给服务端B,并随机产生一个序列号seq为u。
  2. 服务端B应答ACK=1,随机产生一个序列号seq为v,确认序列号ack为u+1,告诉客户端A可以断开,但是需要等待服务端B处理完数据再主动给客户端A发送FIN信号。这个时候客户端A为半关闭状态(FIN_WAIT2),无法再发送数据
  3. 服务端B数据处理完了,主动发送FIN=1信号给客户端A,ACK置为1,随机产生一个序列号seq为w,确认序列号依然为u+1。这是B也进入半关闭状态(CLOSE_WAIT)。
  4. 客户端A接收到B的FIN信号后,发送给服务端B ACK=1信号,序列号为u+1,确认序列号ack=w+1。并且客户端A进入TIME-WAIT状态,经过2MSL(Maximum Segment Lifetime"最大分割时间")后,没有收到服务端B传来的报文,则确认B已经收到A最后发送的ACK指令,此时TCP连接正式释放

TCP四级挥手过程如下图所示:

TIME_WAITCLOSE_WAIT分别表示主动关闭和被动关闭产生的阶段性状态,如果线上服务器大量出现这两种状态,就会加重机器负载,也会影响有效连接的创建,因此需要进行有针对性的调优处理。

  • TIME_WAIT:主要要求关闭的机器表示收到了对方的FIN报文,并发送出了ACK报文,进入TIME_WAIT状态,等待2MSL后即可进入到CLOSED状态。如果FIN_WAIT_1状态下,同时收到了对方发来的带FIN和ACK标志的报文时,可以直接进入TIME_WAIT状态,而无需进入FIN_WAIT_2状态。
  • CLOSE_WAIT:被动要求关闭的机器收到对方请求关闭连接的FIN报文,在第一次ACK应答后,马上进入CLOSE_WAIT状态。这种状态其实表示在等待关闭,并且通知应用程序发送剩余的数据,处理现场信息,关闭相应资源。

在TIME_WAIT等待的2MSL是报文在网络上生存的最长时间,超过阀值报文则会被丢弃。一般来说MSL大于TTL衰减至0的时间。在RFC793(先行的TCP协议)中规定为2分钟,但是在当前的高速网络中,2分钟无疑是一种巨大的资源浪费,在高并发服务器上通常会使用更小的值。

Q:既然TIME_WAIT状态百害而无一利,为什么不直接关闭,进入CLOSED状态呢?

A:原因有如下两点:

  1. 确认被动关闭方能正常进入CLOSED状态。如上图所示,如果客户端A发送的最后一个ACK由于网络原因导致无法到达服务端B,处于LAST_ACK的B机器通常“自信”地以为对方没有收到自己的FIN+ACK报文,所以会重发一次FIN+ACK。客户端A收到第二次的FIN+ACK报文,会重发一次ACK,并且重新计时。如果A机器收到B发来的FIN+ACK,并发送一个ACK给B后就直接进入CLOSED状态的话,可能会导致B无法确保收到最后的ACK指令,也就导致B无法进入CLOSED状态。
  2. 防护失效请求。这样做是为了防止已失效连接的请求数据包与正常连接的请求数据包混淆而发生异常。

猜你喜欢

转载自blog.csdn.net/weixin_41047704/article/details/85229912
今日推荐