网络基础3——TCP协议及三次握手四次挥手

本文讲的是传输层的TCP协议,在传输层还有UDP协议,其传输过程及报头格式都较简单,所以不做过多总结。

什么是TCP协议?

简单来说,TCP协议就是面向连接的、可靠的、基于字节流的传输控制协议。它提供全双工通信,每一条TCP连接有两个端点,并且是一对一的(注:这两个端点不是主机,不是主机的IP地址,不是应用进程,不是传输层的协议端口,而是套接字socket)
在这里插入图片描述

TCP报头格式

在这里插入图片描述
16位源端口号:包含初始化通信的端口。源端口号和源IP地址的作用是标识报文的返回地址(数据发起者的端口号)
16位目的端口号:标识报文接收计算机上的应用程序地址接口(数据接受者的端口号)
32位序号:和确认序号一起保证通信双方的可靠性;保证数据按序到达,确认下次发送的序号;明确告诉发送方哪些报文丢失
32位确认序号:收到的确认序号比发送序号大1(比如说我的序号和你的确认序号保证我这个方向上的可靠性)
4位首部长度:表示该TCP头部有多少个32位bit,所以TCP头部最大长度是15*4=60
6位标志位:

  • URG(0x20):标识紧急指针是否有效;当URG=1,表示报文段中有紧急指针,应尽快发送数据
  • ACK(0x10):表示确认序号是否有效;当ACK=1,表示这是一个确认包的TCP包,取值为0则不是确认包
  • PSH(0x08):提示接收端应用程序立刻从TCP缓冲区读走;当发送端PSH=1,接收端应尽快的交付给应用程序;当接受能力为0或变小时,让接收方将接受缓冲区中的数据读走
  • PST(0x04):对方请求重新建立连接;把携带RST的称为复位报文段;当RST=1,表示TCP连接中出现严重错误,必须释放连接,再重新建立连接
  • SYN(0x02):请求建立连接;把携带SYN标识的称为同步报文段;当SYN=1,ACK=0,表示一个连接请求报文段;当SYN=1,ACK=1,表示同意建立连接
  • FIN(0x01):终止。通知对方本端要关闭了,称携带FIN标识的为结束报文段;当FIN=1,表示此报文段发送端的数据已经发送完毕,并要求释放传输连接
    16位窗口大小:基于窗口大小的流量控制;用来控制对方发送的数据量,通知发放已确定的发送窗口上限,存放的是自己的接受缓冲区的剩余空间的大小

TCP的可靠性

没有100%可靠的协议,因为最新一条消息无法保证可靠性!!!
TCP的可靠性表示在六个方面:

  • 面向连接:包括建立连接和断开连接(后面重点讲解!!!)
  • 确认应答:由32位序号和32位确认序号共同组成;每一次发送的消息都需要应答。在确认应答机制中,发送一个数据收到ACK确认应答后再发送下一个数据,这样浪费时间,效率低。所以引入滑动窗口(一次发送多条数据,提高性能,将多个段的等待时间重叠在一起),如下图,窗口大小(无需等待确认应答而可以发送数据的最大值)由对方的接受能力决定。滑动窗口在我的发送缓冲区中,由对方的接受缓冲区决定。
    如果发生丢包,分为两种情况:
    1.数据包已经抵达,ACK丢失,这种情况不要紧,可以通过后续的ACK进行确认。
    2.数据包直接丢失,这时会引入一种“高速重发机制(快重传)”,发送端会一直收到上条数据包的确认消息,期间发送方还会发送数据,当发送方发送丢失的报文并且接收方接受到后,接受方会发送最近一条报文的应答消息,中间发送的消息被接收方放到了接收方的接受缓冲区中。
    在这里插入图片描述
  • 按序到达
  • 丢包、超时重传:指发送的数据丢失或确认应答的包(ACK)丢失。如何确定超时重传的时间呢?如果是理想情况,需要设置一个最小时间,保证“确认应答一定能在这个时间内返回”,但这个时间长短会随着网络环境的不同,有一定的差异。为了保证高性能通信,需要动态计算最大超时时间。在Linux中,超时以500ms为一个单位进行控制,每次判定超时重发的超时时间都是500ms的整数倍;如果重发一次后,仍然得不到应答,等待2500ms后再进行重传;如果仍然得不到应答,等待4500ms进行重传。依此类推,以指数形式递增。累计到一定的重传次数,TCP认为网络或者对端主机出现异常,强制关闭连接。
  • 流量控制:应用16位窗口大小,指导对方的工作;TCP根据接收端的处理能力,来决定发送端的发送速度。
  • 去重功能
  • 拥塞控制:主要针对网络问题或大面积丢包问题。引入一个“拥塞窗口”,发送开始时,定义拥塞窗口大小为1,每次收到一个ACK应答,拥塞窗口加1,每次发送数据包的时候,将拥塞窗口和接受端主机反馈的窗口大小作比较,取较小的值作为实际发送的窗口大小;像这样的拥塞窗口增长速度,呈指数级别,即“慢启动”——初始时慢,增长速度快。但是不能让拥塞窗口单纯的加倍,此处引入一个叫做慢启动的阈值,当拥塞窗口超过这个阈值时,不再按照指数方式增长,而是按照线性方式增长。当TCP开始启动时,慢启动阈值等于窗口的最大值,在每次超时重传的时候,慢启动阈值会变成原来的一半,同时拥塞窗口置回1。!!!拥塞控制,归根结底是TCP协议想尽可能快的把数据传输给对方,但是又要避免给网络造成太大压力的折中方案。

TCP的三次握手和四次挥手

TCP的连接管理机制,一般情况下,要经过三次握手建立连接和四次挥手断开连接
三次握手
在这里插入图片描述
第一次握手:客户端主动向服务器发送一个SYN包,并进入SYN_SENT状态,等待服务器响应。
第二次握手:服务器收到了SYN包,必须确认客户端的SYN包,同时自己也需要发送一个SYN包给客户端,故服务器发送SYN+ACK包给客户端,此时服务器进入SYN_RCVD状态。
第三次握手:客户端收到服务器发送的SYN+ACK包,向服务器发送确认包ACK,此时客户端和服务器都进入ESTAB_LISHED状态,自此三次握手完成。
所以问题来了,为什么是三次握手?而不是一次、两次、四次呢?
若是一次握手,那么客户端和服务器双方都认为连接建立不成功。
若是两次握手,服务器认为连接建立成功,而客户端认为不成功,此时服务器就会花费资源,客户端太多会导致服务器崩溃。
三次握手已经确保建立连接不需要四次。
在三次握手中,客户端最后发送ACK确认包,此时客户端认为连接建立成功,服务器认为不成功,若是最后的ACK发生丢包现象,连接建立异常,就将这个连接放在了客户端上,不会产生太大影响。过一段时间后,服务器没有收到ACK包,会重新发送连接请求。所以三次握手建立连接的最大优点就是如果握手失败,连接建立异常时,将异常放在客户端上。

四次挥手
在这里插入图片描述
一次挥手:客户端向服务器发送连接释放报文FIN,并停止发送数据。此时,客户端进入FIN_WAIT_1状态。
二次挥手:服务器收到释放报文FIN,并发出确认报文ACK。此时,客户端向服务器方向的连接就断开了,这时处于半关闭状态(客户端已经没有数据要发送了,但要是服务器发送数据,客户端依然要接受),这个状态也就是整个CLOSE_WAIT状态持续的时间。
三次挥手:客户端收到服务器的确认请求后,客户端进入FIN_WAIT_2状态,等待服务器发送连接释放报文。服务器将最后的数据发送完毕后,就向客户端发送连接释放报文FIN。此时,客户端进入LAST_ACK状态,等待客户端最后的确认。
四次挥手:客户端此时收到了服务器的连接释放报文FIN,必须发出确认。客户端进入TIME_WAIT状态。此时TCP连接还没有释放,必须经过2MSL(最长报文生存时间)后,客户端撤销了相应的TCB,才进入CLOSED状态。服务器只要收到了客户端发出的ACK确认报文,立刻进入CLOSED状态。所以,服务器结束TCP连接的时间要比客户端早一些。
那么为什么TIME_WAIT状态要经过2MSL才能回到CLOSED状态??
按一般思维来说,四个报文都发送完毕,就可以直接进入CLOSED状态,但是网络环境是不可靠的,最后一个客户端发送的ACK报文不能保证服务器一定收到了,如果发送完直接进入CLOSED状态,有可能发生丢包现象却没有解决。如果最后一个ACK丢失,那么服务器将会不断重复发送FIN报文,所以客户端不能立刻关闭要等待2MSL,确认服务器收到了ACK报文,TIME_WAIT状态就是用来重发可能丢失的ACK报文,如果在2MSL中再次收到了FIN,那客户端就会重发ACK并再次等待2MSL。如果没有收到,故客户端认为服务器收到了ACK,则结束TCP连接。
为什么建立连接时是三次握手,关闭时是四次挥手??
当服务器收到SYN后,可以直接发送SYN+ACK,ACK是用来应答的,SYN是用来同步的。
但是关闭连接时,当服务器收到FIN时,很可能不会立即关闭连接,因为可能有没发完的数据,所以只能先回复一个ACK报文,告诉客户端:“你发的FIN我收到了,等我所有的报文都发完了,我才能发送FIN报文”,故断开连接时FIN和ACK不能一起发送,所以需要四次挥手。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值