TCP的原理,作为一个应用开发者来说,可能在平常开发中,99%时间用不上。因为平常用得网络框架比如OkHttp等都已经帮我们封装好,我们不需要知道里面的原理直接用接口即可,很简单。
但是作为一个优秀的开发者,我们必须要知其然也需要知其所以然。而且特别在面试的时候, TCP握手和挥手原理经常被问到,如果答得上来,容易加分....
闲话少说,直接上原理图
【三次握手】
具体流程:
1:客户端(Client)尝试请求连接,会随机产生一个数Sequence码 X,发给服务端(Server)
2:服务端拿到了客户端发过来的 Sequence码 X ,会 将 X + 1 生成 ACK码,然后自己也会随机产生一个数Sequence码Y
然后把ACK 和 Y 一同打包发给 客户端
3:客户端拿到服务端反馈的 ACK 和 Sequence码,先验证 Sequence码 X 是否加了1,是就代表服务端反馈的就是自己之前的请求。 然后再把 Sequence码Y 加 1,生成ACK码,把 ACK码返回给服务端。
(同理服务端也会验证 返回的ACK码是否在Sequence码Y基础上加了1 )
至此,握手通讯成功,可以传递数据...
疑问1:为什么传递数据前要3次握手通讯,而不是直接传递数据呢??????
因为要保证连接的有效性,避免资源浪费。试想客户端发了连接请求给服务端,由于网络拥挤等异常原因,请求迟迟发送不到服务端,这时客户端收不到反馈数据,早下线掉线了。过了几个小时服务端才收到请求,如果这时不握手验证,直接就把数据返回过去,这就造成资源的浪费。如果在数据传递前验证握手通讯,即可保证双方都“在线”,也可以保证 请求-返回 是一一对应的。
【四次挥手】
具体流程:
1:客户端尝试断开连接,会发送断开TCP连接请求的报文,会将FIN置1,并会随机产生 Sequence码 M,发给我 服务端
2:服务端收到 TCP连接请求报文,会将M+1 生成 ACK码,返回给客户端,客户端接收到自己的 Sequence码 加了1,说明断开 请求已经得到验证。
3:服务端在收到断开TCP连接请求的报文,并不会立马断开连接,而是等自己的数据全部都发送出去才会断开连接。所以服务端在保证已经把所有数据发送出去之后,把FIN置1,产生随机产生Sequence码N,把N发送给客户端。
4:客户端收到服务端的请求断开报文,会把 N+1 生成ACK,反馈给服务端。服务端校验到ACK是在Sequence码N加了1,从而完成服务端请求的验证回复。
至此,4次挥手完成。
疑问2:断开前要4次挥手,而不是直接断开连接呢???
因为 TCP连接是全双工的,一方需要断开,得另一方确认,这样一来一回就是四次通讯了。再者这么设计,也是为了保证数据传输的完整性。因为Client发送了断开报文,仅仅代表Client没有了数据传递过来,Client还能接受数据。如果Server接收到断开报文就立马断开,假如此时还有剩余数据没有传输完呢?这样直接断开就会造成数据传递丢失了。所以服务端会先同意客户端的断开请求,再确保服务端自己已经把全部数据发送完,再发送断开报文给客户端。所以步骤2和3一般是分开来发送的。所以这样一来一回的挥手,就是4次挥手了。
疑问3:4次挥手,能不能改成3次挥手?
可以!只要服务端在收到断开报文时,已经确保了所有数据已经发送完了。这样步骤2和3可以合在一起发送。这样就是三次挥手了。不过,一般会分开来发送的。