杭州网站建设优化推广,怎么建个自己的网站,全新的手机网站设计,外贸网站框架一#xff0c;TCP基本概念 TCP的特性#xff1a; TCP是有连接的#xff1a;TCP想要通信#xff0c;就需要先建立连接#xff0c;之后才能通信 TCP是可靠传输#xff1a;网络上进行通信#xff0c;A给B发消息#xff0c;这个消息是不可能做到100%送达的#xff0c;所以…一TCP基本概念 TCP的特性 TCP是有连接的TCP想要通信就需要先建立连接之后才能通信 TCP是可靠传输网络上进行通信A给B发消息这个消息是不可能做到100%送达的所以这里的可靠传输是指A给B发消息A能知道消息是否到达B如果发送失败A会采取一些措施比如数据重传 TCP是面向字节流的TCP是以字节位单位进行传输的 TCP是全双工的TCP可以实现双向通信 二TCP协议端格式 TCP协议中的源端口目的端口和校验和与UDP协议中的一样这里不过多赘述。我们先了解一些简单的头部长度保留和选项其他的后面讲。 头部长度代表TCP报头的长度报头最短是20个字节(即没有选项)最长是60个字节(即选项拉满)虽然只有 4 bit 但是此处的单位是4个字节所以可以表示60个字节的长度。选项英文是option可选择的。也就是说这个区域可以有也可以没有还有一点选项的单位是4个字节最大值是 40 个字节。保留因为在UDP协议中它的数据包长度只有64kb改不了所以大佬在设计TCP协议的时候对其进行了优化如果需要增加长度就可以使用保留位。 三TCP原理
3.1 确认应答
为了实现可靠传输发送方把数据发给接受方之后接收方收到数据就会给发送方返回一个应答报文(acknowlege简写 ack)如果发送方收到应答报文就知道自己的数据发送成功了。但是在网络通信时可能会出现下图的情况 TCP协议要确保两个点 确保应答报文和发送方发送的数据能匹配。确保当发生 后发先至 的情况时能够让程序仍然能按照正确的顺序读取数据。 这个时候TCP协议中的序号和确认序号就发挥出作用了。序号和确认序号是相互匹配的。 假设序号从1开始每次传输的TCP载荷中有1000个字节的数据如下图 如果发生后发先至的情况我们的程序也会根据序号重新调整顺序。确保按照正确的顺序读取数据这里还需要注意的是我们如何来区分一个数据报是普通的数据还是ack应答数据呢 ACK这一位是1就表示当前数据报是一个ack应答报文此时确认序号字段生效。这一位为0就表示当前数据报是一个普通报文此时确认序号字段不生效。
注确认应答是实现TCP可靠传输最核心的机制
3.2 超时重传
确认应答描述的是一个比较理想的情况但是数据在网络传输过程中也有可能会出现 丢包 的情况这时我们的发送方势必就无法收到ack应答报文了。这里的超时重传机制就是对确认应答的一个补充。
首先先来了解一下为什么会发生 丢包 我们可以将网络想象成错综复杂的高速公路在高速公路上有许多的收费站一到节假日就会出现堵车。而在网络中路由器/交换机就类似于收费站如果数据包太多了就会在路由器/交换机上出现堵车但是路由器对于堵车的处理往往是比较粗暴的它会将其中大部分的数据包直接丢掉此时这些数据包就在网络上消失了。
实际上丢包是一个随机事件它是由当前的基础设施和网络环境决定的因此在TCP传输过程中丢包就存在两种情况 而发送方是无法区分这两种情况的所以发送方都会进行 重新传输。发送方发送完数据之后会等待一段时间如果这个时间之内收到了ack此时一切正常如果到达这个时间之后还没收到ack就会触发重传机制。 这里的等待时间是不确定的 1初始的等待时间始可配置的不同系统上的都不一定一样 2等待的时间也会动态变化每多经历一次超时等待的时间就会变长。而当时间长到一定的程度就认为数据不可能传输成功了就会触发TCP的重置连接操作(假设丢包概率为10%第一次失败概率为10%第二次失败概率就是1%当出现多次丢包时就说明丢包的概率远远大于10%很可能出现了严重的网络故障这时候传得再快也没用) 实际上如果是 ack 丢了触发超时重传还会导致一个严重的问题 —— 就是接收方会收到两份一模一样的数据比如你用线上支付时ack丢了触发超时重传你就会多付一份钱。但是在实际生活中却不会发生这种情况这是为什么呢
因为TCP协议已经帮我们把这个问题给解决掉了TCP中存在一个 接收缓冲区 这是一块内存空间它会保存当前已经接收到的数据以及数据的序号如果发送方发来的数据是已经在接收缓冲区中存在的是重复数据根据序号来判断是否是重复数据接收方会直接把这个后来的数据丢掉确保程序进行 read 的时候不会读到重复数据。
此外接收缓冲区也能进行重新排序确保发送顺序和应用程序读取的顺序是一致的。
3.3 连接管理 - 建立连接断开连接
这个机制是面试中对经典的问题三次握手和四次挥手下面我们来详细的讲一讲
3.3.1 三次握手 - 建立连接
TCP这里的握手就是给对方发送一个简短的没有业务数据的数据包通过这个数据包来唤起对方的注意从而触发后续的操作。注这里的握手操作不是TCP独有的计算机中的很多操作都涉及到 握手
TCP的三次握手是TCP在建立连接的过程中需要通信双方一共打 三次招呼 才能完成连接如下图所示 此时握手完成A 和 B 都记录了对方的信息建立连接的过程实际上是通信双方都给对方发起 syn也都要给对方反馈 ack一共是 4 次握手但是中间两次可以合并成一次所以叫做 “三次握手”。为什么可以合并因为 ack 和 syn 都是内核触发的是同时触发所以可以合并。
那么我们如何来区分一个数据包是不是 syn 呢和 ack 一样TCP协议中也有一块空间 SYN这一位是1就表示当前数据报是一个syn同步报文段。这一位为0就表示当前数据报是一个普通报文。如果 SYN 和 ACK 同时为 1就表示当前数据包既是一个 syn 同步报文段也是一个 ack 应答报文。
了解三次握手的流程之后这里还有两个问题1. 三次握手解决了什么问题2.为什么需要三次握手来建立连接两次握手行不行
1TCP协议就是为了实现 可靠传输而 确认应答 和 超时重传 有一个大前提就是当前的网络是通畅的如果当前网络已经存在重大故障那么可靠传输就无从谈起。而三次握手就是来检查当前网络是否是通畅的。
2三次握手是为了让发送方和接收方都能确认自己的发送能力和接收能力均正常靠两次握手实现不了看图就理解了 总结三次握手的作用 确认当前的网络是否畅通让发送方和接收方都能知道双方的发送能力和接受能力均正常让通信双发在握手过程中针对一些重要的参数进行协商 3.3.2 四次挥手 - 断开连接 与三次握手不同此处的四次挥手能否将中间的两次交互合二为一答案是不一定 不能合并的原因ACK 和 FIN 的触发时机是不同的ACK 是内核响应的B一接收FIN就会立即返回 ACK而 FIN 是应用程序的代码触发B 这边调用 close 方法才会触发FIN而在执行 close 代码之前还需要多长时间是不确定的所以不能合二为一。可能合并的原因TCP中还有一个机制延时应答(后面讲)能够拖延 ACK 的回应时间一旦 ACK 滞后了就有机会和下一个 FIN 合并了。 这里还有一个注意点 —— 上图中存在TIME_WAIT 状态(哪一方主动断开连接哪一方就会进入TIME_WAIT)为什么A接收到FIN发送 ACK 之后不立即关闭呢
TIME_WAIT 存在的意义就是为了防止最后一个ACK出现丢包留下的后手。如果最后一个ACK丢了站在B的角度B就会触发超时重传重新发送FIN如果 A 没有 TIME_WAIT 状态就意味着 A 已经关闭了B就永远不可能收到 ACK 了在多次触发超时重传后B也会关闭但这样太浪费时间了。而如果 A 有 TIME_WAIT 状态在放送ACK后A会进入等待等待的这个时间就是为了处理B重新发送的FIN如果有重传的FINA会继续返回ACK。
TIME_WAIT 的等待时间是多长假设网络上两个节点的通信消耗的最大时间是 MSL那么此时的TIME_WAIT就是 2 MSL.
3.4 滑动窗口
前面的三个机制都是在保证TCP协议的可靠传输而TCP协议的可靠传输是会影响传输效率的滑动窗口就是在保证可靠传输的前提下提高传输效率的一个机制。
滑动窗口是通过缩短确认应答的等待时间来提高效率的我们知道正常传输数据是每收到一个应答报文再发送下一个数据在这个过程中等待的时间比较长。而滑动窗口使用批量传输数据的方式不用等待 ACK直接发送下一个数据如下图 这个窗口是有上限的达到上限后会统一等待ack这个上限就是窗口的大小之后就是返回一个ack就再发送一个数据从整体看就像一个滑动的窗口。
上述的滑动窗口中确认应答是可以正常工作的但是如果出现了丢包怎么办这里的重传相比于超时重传又有所不同
情况一ack丢了 这种情况不需要任何重传确认序号的含义是当前序号之前的数据已经确认收到了你应该从确认序号这里继续发送比如上图中返回的确认序号1001丢了但是返回的确认序号2001没丢那么2001之前的数据都会确认为传输成功了涵盖了1001的情况。
情况二数据包丢了 由于1001~2000这个数据没了此处的ack仍然索要 1001无论传过来的是几都索要 1001。当 A 这边发现 B 连续几个ack都在索要 1001A就知道1001这个数据丢了就会重传 1001~2000的数据重传之后B 就会接着索要 5001 了。上述重传过程比较快没有冗余操作也称为快速重传。
注这里的滑动窗口不是一直使用如果通信双方传输的数据量比较小也不频繁就是普通的确认应答如果通信双方传输的数据量比较打也比较频繁就会进入滑动窗口模式按照快速重传的方式处理。
3.5 流量控制
滑动窗口的大小与流量控制有关虽然窗口越大传输的效率就越大但是传输效率也会受到处理效率的制约如果传输的速度太快就可能会导致接收方处理不过来了此时接收方就会出现丢包发送方还得重传这就有点得不偿失了。所以发送方的发送效率不能超过接收方的处理效率。
那这里就出现了一个问题用什么来衡量接收方的处理能力之前提过TCP有一个接收缓冲区A 发给 B 的数据会先到达 B 的接收缓冲区然后 B 再调用 read 这样的方法把数据从缓冲区中读取出来再进一步进行处理一旦数据被 read就可以从缓冲区中删除了那么这里我们就可以把接收方缓冲区剩余的空间大小作为衡量处理能力的指标剩余的空间越大处理能力就越强剩余空间越小处理能力就越弱。
接收方每次收到数据后都会把接收缓冲区的剩余空间大小通过ack应答报文返回给发送方发送方就可以通过这个数值来调整下一轮的发送速度如下图所示 如果等待的时间超过了重发超时的时间就会周期性的发送一个窗口探测包并不携带业务数据就是为了触发 ack为了查询当前接收方的接收缓冲区剩余空间。
TCP中的窗口大小就是用来存储接收缓冲区剩余空间大小的但是这不代表接收缓冲区最大为64kb因为再选项中也有一些参数是来存储接收缓冲区的。 3.6 拥塞控制
流量控制考虑的是接收方的处理能力但是在网络传输过程中不仅仅只有发送方和接收方参与还有中间的路由器/交换机等也会参与所以我们还需要考虑这些路由器/交换机的效率但是这些节点结构更加复杂也就无法进行量化因此我们使用 实验 的方式来找到合适的值。
实验过程如图所示 注流量控制和拥塞控制都是在限制滑动窗口的大小最终发送的窗口大小取 min(流量控制拥塞控制)。
3.7 延时应答
正常情况下A 把数据发给 BB 就会立即返回 ack 给 A但是也有时候A 传输给 B 此时 B 会等一会再返回 ack 给 A这就是延时应答。
延时应答本质上也是为了提高传输效率延时返回ack就意味着接收方有更多的时间去处理数据也就能读取更多数据接收缓冲区的剩余空间就会更大返回的窗口大小也会更大从另外一个角度变相的增大了滑动窗口的大小。
3.8 捎带应答
捎带应答是在延时应答的基础上进一步提高效率在网络通信中往往是这种 一问一答 这样的通信模型。 通过延时应答和捎带应答ack 和 响应 就可以合并成一个数据包一起返回给 A 了与三次挥手类似。 这里的需求和响应是业务上的数据
3.9 面向字节流
这里有一个严重的问题——粘包问题这个问题不是tcp独有的而是面向字节流的机制都会有类似的问题。什么是粘包问题举一个例子A 向 B 传输了三个数据aaabbbccc而储存到B接收缓冲区的是 aaabbbcccB无法区分A传输了几个数据以及每个数据的内容。
如何解决粘包问题核心思路通过定义好的应用层协议明确应用层数据包之间的边界。有两种方式1引入分隔符 2引入长度
1假设分隔符为 \n 2引入长度 3.10 异常情况的处理
在使用TCP的过程中出现意外会如何处理 1进程崩溃 就是进程异常终止了文件描述符表也就释放了此时会触发FIN对方收到后会返回FIN和 ACK这边再返回FIN就是正常的四次挥手断开连接TCP的连接独立于线程之外 2主机关机主动关机 在关机过程中会先触发强制进程终止操作和1相同但是不仅仅是进程没了整个系统也可能关闭了如果在系统关闭之前对端返回的FIN和ACK到了此时系统可以返回ACK进行正常的四次挥手。如果系统已经关闭了FIN和ACK来迟了系统无法返回ACK站在对端的角度以为是FIN丢包了就会重传FIN重传几次FIN都没响应自然就会放弃连接。 3主机掉电非正常 此时是一瞬间的事来不及关闭进程也来不及发送FIN 1. 接收方掉电发送方在发送数据等待ack触发超时重传多次重传后会触发TCP来连接重置功能发送 复位报文段如果复位报文段发送之后还是没有响应就会释放连接。 2. 发送方掉电接收方在接收数据接收方会一直等待数据这时接收方无法区分是对方没发消息还是对方挂了TCP提供了心跳包机制接收方也会周期性的给发送方发起一个特殊的不携带业务数据的数据包并且期望对方返回一个应答如果对方没有应答并且重复多次之后仍然没有就视为对方挂了此时就可以单方面释放连接了。 4网络断开 —— A给B发送数据 A就相当于 31 B就相当于 32