🌈个人主页:努力学编程’
⛅个人推荐:
c语言从初阶到进阶
JavaEE详解
数据结构
⚡学好数据结构,刷题刻不容缓:点击一起刷题
🌙心灵鸡汤:总有人要赢,为什么不能是我呢
🔥🔥🔥TCP核心机制(一)
对于TCP来说,我们知道其基本的特性为:有连接,可靠传输,面向字节流,全双工.除了可靠传输之外,我们都可以通过TCP简单的回显服务器,客户端中体现这些特点.
对于TCP来说,可靠传输并非是可以保证数据可以100%传输成功的,而是尽力的数据传输,等待收到数据的时候,会发送一个确认应答的信息.我们将这个TCP的机制就成为确认应答机制
举一个例子:
一天,我邀请我的白月光去吃烤肉,等到放学之后,我就会给她发消息,“女神女神,有空吗,我请你吃烤肉” 此时女神看到我的信息,无论她去与不去都会给我发一个信息,来保证她收到了我的信息, 这个过程就类似确认应答机制
我们将TCP机制中收到数据后,发送的确认应答的数据称为应答报文.一般缩写为ack,
但是,确认应答机制还有很多的问题,比如当我们发送多个数据的时候,可能机会出现歧义~
如果我给女神发了这样几条信息: 女神女神,我请你吃烤肉 女神你做我女朋友怎么样
女神是这样回复我的: 好啊好啊 滚damn!
此时网络中可能会有这么一件情况:后发先至,就是女神给我发的信息,并没有按照顺序给我发过来,此时就可能有这样的一种情况:
那么此时就会导致我们所收到的数据,发生歧义,这个状况我们称为后发先至.
发生 “后发先至” 的原因就要追溯到网络的历史,网络最开始的时候,是用于军事的,之前用互联网来控制核弹的发射,为了不让敌方破坏这个信息通道,就会在两方建立不止一条线路,这样错综复杂的多条线路就构成了互联网的雏形.
我们在发送多条数据的时候,不一定走的是同一条路线,这样数据就不一定会按照之前的顺序发送给接收方.
为了解决 ''后发先至" 的情况,我们可以给发送的每条信息编号,这样即使数据延迟发送,后面也可以被正确接收
由于TCP是面向字节流的,我们在实际场景中并非是按照 “第一条,第二条"这样的方式来编排的,而是"字节” 第一条字节,第二条字节
每个字节都有独立的编号,字节和字节之间是连续的,递增的.
按照字节编号这样的机制,就称为"TCP的序号"
在应答报文中,针对收到的数据进行的编号,就成为"TCP的确认序号"
==由于编号是连续递增的,我们就只要记录第一个字节的编号就好.
🔥🔥🔥TCP核心机制二(超时重传)
在网络传输中并不是一帆风顺的,江湖仓可能发生丢包现象,原因有很多种:
- 在数据传输的过程中发生了 bit 翻转,导致接收方收到数据/中间的路由器计算校验和的时候,发现对不上,此时就会立即停止传输这个数据,不能讲错就错,并将这个数据丢弃~
- 传输的数据太多,传输到某个节点时负载太大(路由器只能发N个包,此时你发的包的数量已将超过N了,后面就会对发来的数据进行丢包操作~)
那么TCP是怎么预防丢包问题的呢? 首先TCP是无法直接干预丢包操作的,它只能通过应答报文,来感知这个数据有没有收到,如果此时没有收到这个数据的应答报文,并不意味着,这个数据已经丢失了,因为数据传输也是需要时间的,可能过一会数据就传过来了,一般发送方在发送数据之后,会给一个 “时间限制” 过了这个时间之后,就会默认数据已经丢包了,此时就会对数据再次重传,等待应答报文,
由于数据在时间限制之内没有被接收的话,就会触发重传操作,那么有没有这中可能呢:数据已经传输给接收方了,但是接收方的应答报文却丢失了,此时由于发送方一直没有等来应答报文,就会对数据重传,就会发生以下情况:
那么B就会就收到两份数据,那么TCP是如何避免这种情况的发生的呢
TCP有这样的机制,接收方这边有一个内存缓冲区,每次接收到数据之后,就是把数据放到内存缓冲区中,如果后面再收到数据,就会将数据放到内存缓冲区中(排序),此时如果发现已将有了这个数据的信息,就不会再保存这个数据,而是直接丢包~
超时重传 的时间是可以自己设定的,是动态变化的,超时重传也不是无休止的,每一次重新发送数据的时候,时间间隔都会变大,因为每次重新发送数据的时候,接受方收到数据的几率就会越来越大,如果此时还还没有接收到应答报文的话,接收方就会发送一个 “重置/连接”(复位报文) 等待网络恢复的时候,可能就会重新建立连接,如果网络依然有很大问题,且复位报文没有收到ack,那么此时接收方就单方面放弃来连接~(将对方的数据删除)
🔥🔥🔥TCP 的可靠传输
对于TCP 的可靠传输,我们是依赖 “超时重传” 和 “确认应答” 来保证的,网上很多资料说 TCP的可靠传输 是因为 “三次握手,四次挥手” 决定的, 其实 “超时重传” 和 “确认应答” 才是最主要的原因, “三次握手,四次挥手” 只是起到了一个辅助的作用~
🔥🔥🔥TCP核心机制三(建立连接)
🌟🌟🌟三次握手🌟🌟🌟
网络中建立连接和断开连接的操作即(三次握手,和四次挥手) 这里的握手指的就是建立连接和断开连接的过程,握手是一个形象的比喻~
网络中的 “握手” 发送的是不携带数据的空数据包,只是起到了一个 “打招呼” 的效果~
三次握手,四次挥手是非常高频的网络面试题目
下面给大家画一下 “三次握手” 的整个过程~
首先A给B法送信息,说我想和你建立连接,B收到请求之后,发送ack回应信息,然后B也回给A发送信息:我想和你建立连接,此时A也会发送一个ack,表示可以建立连接~
你可能会这不是4步吗,其实真是的过程是将服务器这端的syn和ack做了一个整合,将两个过程化为一个过程.因为分两步肯定没有一步的开销小且每个数据包都是需要封装的,即:
这就是三次挥手的整个过程了.
🌟🌟🌟四次挥手🌟🌟🌟
在三次握手之后,我们传输完数据之后,就要进行断开连接的操作,这里的四次挥手就是 “优雅的断开连接” 并且不是只有客户端才能主动发送信息,服务器也可以主动发送断开连接的信息,都得给对方发送 FIN 和 ack 信息,完成四次挥手的整个过程~
对于三次握手来说,ack和syn都是同一时间,且都是由操作系统内核完成的,所以可以将这两个过程合并,但是在四次挥手中,ack是操作系统内核完成的,而FIN则是由应用程序调用 close 关闭,释放程序~
🔥🔥🔥TCP的状态信息🔥🔥🔥
其实TCP也是有状态的: LISTEN 服务器进入的状态,服务器将端口绑定好,相当于进入 listen 状态了,
此时服务器已经初始化完毕了,随时准备好迎接客户端了.
相当于 手机开机,信号良好,随时可以有人来打电话了~
ESTABLISHED 客户端和服务器都会进入的状态:
建立,设立的意思
TCP 连接建立完成(保存了对方的信息了)接下来就可以进行业务数据的通信了.
电话接通了,可以说了~
CLOSE_WAIT 被动断开连接的一方,会进入这个状态,先收到FIN的一方, “等待代码close方法”,
TIME_WAIT 主动断开连接的一方,会进入的这个状态~~ 此处的TIME_WAIT 按照时间来等待,达到一定时间后,连接也就释放了
此处直接释放的原因是 防止最后的ACK丢包~~