一:引出

客户端与服务器之间数据的发送和返回的过程当中需要创建一个叫TCP connection的东西;由于TCP不存在连接的概念,只存在请求和响应,请求和响应都是数据包,它们之间都是经过由TCP创建的一个从客户端发起,服务器接收的类似连接的通道,这个连接可以一直保持,http请求是在这个连接的基础上发送的;在一个TCP的连接上是可以发送多个http请求的

二:TCP的报文格式

1:TCP在传输层和网络层数据传输的过程

TCP协议是在传输层端到端的传输信息,既然说到传输层协议,那么就讲一下传输层协议在数据传输过程中的位置:在这里插入图片描述
左边家庭要给右边家庭通信中的(应用层和传输层和网络层)
左边家庭的孩子小红(应用层中 应用进程)写了一封信(应用消息),然后小红将信交给了哥哥李雷(传输层),李雷将信放入到家门口的信箱里,邮递员来了将信取走放到了邮政汽车上,然后邮政汽车肯定不是直达的,他们到了转运中心(路由器)转到另一辆汽车上根据时间成本,路线成本等选择一条路继续运输(网络层)。

2:TCP报文

在这里插入图片描述
其中比较重要的字段

a:序号(sequence number):

Seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。

对序号的补充:
应用层向TCP层发送用于网间传输的、用8位字节表示的数据流,然后TCP把数据流分区成适当长度的 报文段 (通常受该计算机连接的网络的 数据链路层 的 最大传输单元 ( MTU )的限制)。之后TCP把结果包传给IP层,由它来通过网络将包传送给接收端实体的TCP层**。TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。**然后接收端实体对已成功收到的包发回一个相应的确认( ACK );如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。TCP用一个 校验和 函数来检验数据是否有错误;在发送和接收时都要计算校验和。

b:确认序号(acknowledgement number):

Ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,Ack=Seq+1。

c:标志位(Flags):

共6个,即URG、ACK、PSH、RST、SYN、FIN等。具体含义如下
URG:紧急指针(urgent pointer)有效。
ACK:确认序号有效,确认接收到消息;
PSH:接收方应该尽快将这个报文交给应用层。
RST:重置连接。
SYN:发起一个新连接。
FIN:释放一个连接。

在这里插入图片描述

三:TCP的三次握手的图示

1:图示

所谓的三次握手即TCP连接的建立。这个连接必须是一方主动打开,另一方被动打开的。
以下为客户端主动发起连接的图解:
在这里插入图片描述

2:客户端各个状态:

CLOSED状态:为关闭状态
SYN_SENT状态:为请求连接状态, 当你要访问其它的计算机的服务时首先要发个同步信号给该端口,此时状态为SYN_SENT,如果连接成功了就变为ESTABLISHED,此时SYN_SENT状态非常短暂。
ESTABLISHED状态:连接成功

3:服务端的各个状态:

LISTENING状态:监听状态, State显示是LISTENING时表示处于侦听状态,就是说该端口是开放的,等待连接,但还没有被连接。就像你房子的门已经敞开的,但还没有人进来。
SYN-RCVD状态:收到和发送一个连接请求后等待对方对连接请求的确认。
ESTABLISHED状态:连接成功

补充:SYN-RCVD状态
当服务器收到客户端发送的同步信号时,将标志位ACK和SYN置1发送给客户端,此时服务器端处于SYN_RCVD状态,
如果连接成功了就变为ESTABLISHED,正常情况下SYN_RCVD状态非常短暂。如果发现有很多SYN_RCVD状态,那你的机器有可能被SYN Flood的DoS(拒绝服务攻击)攻击了。

SYN Flood的攻击原理是:
在进行三次握手时,攻击软件向被攻击的服务器发送SYN连接请求(握手的第一步),
但是这个地址是伪造的,如攻击软件随机伪造了51.133.163.104、65.158.99.152等等地址。
服务器 在收到连接请求时将标志位 ACK和 SYN 置1发送给客户端(握手的第二步),
但是这些客户端的IP地址都是伪造的,服务器根本找不到客户机,也就是说握手的第三步不可能
完成。这种情况下服务器端一般会重试(再次发送SYN+ACK给客户端)并等待一段时间后丢弃这个
未完成的连接,这段时间的长度我们称为SYN Timeout,一般来说这个时间是分钟的数量级
(大约为30秒-2分钟);一个用户出现异常导致服务器的一个线程等待1分钟并不是什么很大的问题,
但如果有一个恶意的攻击者大量模拟这种情况,服务器端将为了维护一个非常大的半连接列表而
消耗非常多的资源----数以万计的半连接,即使是简单的保存并遍历也会消耗非常多的
CPU 时间和内存,何况还要不断对这个列表中的IP进行SYN+ACK的重试。
此时从正常客户的角度看来,服务器失去响应,这种情况我们称做: 服务器端受到了
SYN Flood攻击(SYN洪水攻击 )

百度百科

4:TCP三次握手的过程

握手之前主动打开连接的客户端结束CLOSED阶段,被动打开的服务器端也结束CLOSED阶段,并进入LISTEN阶段。随后开始“三次握手”:

a:首先客户端先向服务器端发送一个TCP报文

标记位为SYN,表示“请求建立新连接”;
序号为Seq=X(X一般为1)(传输信息的时候每个数据包的序号);
随后客户端进入SYN-SENT阶段(请求连接的阶段)。

b:服务器端收到来自客户端的TCP报文之后,结束LISTEN阶段。并返回一段报文

标志位为SYN和ACK,表示“确认客户端的报文Seq序号有效,服务器能正常接收客户端发送的数据,并同意创建新连接”(即告诉客户端,服务器收到了你的数据);
序号为Seq=y;(返回一个收到信息的数据包 并给其标序号为y)
确认号为Ack=x+1,表示收到客户端的序号Seq并将其值加1作为自己确认号Ack的值(两端配对 接收到消息 并反馈的过程;随后服务器端进入SYN-RCVD阶段。
ACK:代表确认收到消息

c:客户端接收到来自服务器确认收到数据的TCP报文后,明确了从客户端到服务器的数据传输是正常的,结束SYN-SENT阶段,并返回一段TCP报文

标志位为ACK,表示“确认收到服务器端同意连接的信号”(即告诉服务器,我知道你收到我发的数据了);
序号为Seq=x+1,表示收到服务器端的确认号Ack,并将其值作为自己的序号值;
确认号为Ack=y+1,表示收到服务器端序号Seq,并将其值加1作为自己的确认号Ack的值;
随后客户端进入ESTABLISHED阶段。(即成功建立了连接)

d:关于确认号Ack和数据包的序号Seq值得变化

Ack确认号:就是确认收到消息后 返回给 发送端的 序号(Ack = 发起方的Seq + 1) 即就是下次发送的端的seq序号
ACK确认序号(Seq)有效:确认发送的数据包的成功到达
Seq:序号:给每个数据包一个序号,保证接受端可以按序收到数据包(首次握手的时候 Seq = 上次握手的时候的Ack值,如果没有 则可以是任意值)

在客户端与服务器端传输的TCP报文中,双方的确认号Ack和序号Seq的值,都是在彼此Ack和Seq值的基础上进行计算的,这样做保证了TCP报文传输的连贯性。一旦出现某一方发出的TCP报文丢失,便无法继续"握手",以此确保了"三次握手"的顺利完成

5:为甚要三次握手

a:为了防止服务器端开启一些无用的连接增加服务器开销

第一次握手客户端发送的TCP报文,服务端成功接收;然后第二次握手,服务端返回一个确认收到消息的TCP报文,但这个报文因为某些原因丢失了,那么客户端就一直收不到这个TCP报文的

,客户端设置了一个超时时间,超过了就重新发送一个TCP连接请求,那么如果没有第三次握手的话,服务端是不知道客户端是否收到服务返回的信息的,这样没有给服务器端一个创建还是关闭连接端口的请求,服务器端的端口就一直开着,等到客户端因超时重新发出请求时,服务器就会重新开启一个端口连接。那么服务器端上没有接收到请求数据的上一个端口就一直开着,长此以往,这样的端口多了,就会造成服务器端开销的严重浪费。

b:防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。

已经失效的客户端发出的请求信息,由于某种原因传输到了服务器端,服务器端以为是客户端发出的有效请求,接收后产生错误。

c:总结

也可以这样理解:“第三次握手”是客户端向服务器端发送数据,这个数据就是要告诉服务器,客户端有没有收到服务器“第二次握手”时传过去的数据。若发送的这个数据是“收到了”的信息,接收后服务器就正常建立TCP连接,否则建立TCP连接失败,服务器关闭连接端口。由此减少服务器开销和接收到失效请求发生的错误。(如果第三次握手失败的话,那服务端就关闭连接)

参考自

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐