东莞360推广的网站是谁做的,建设的比较好的网站,禅城顺德网站建设,做一个网站美工多少钱网络协议 TCP协议 文章目录 网络协议 TCP协议1. TCP协议段格式2. 可靠传输保障机制2.1 确认应答2.2 超时重传 3. 连接保障机制3.1 三次握手#xff08;建立连接#xff09;3.2 四次挥手#xff08;断开连接#xff09;3.3 TCP状态转换过程 4. 传输效率保障机制4.1 滑动窗口…网络协议 TCP协议 文章目录 网络协议 TCP协议1. TCP协议段格式2. 可靠传输保障机制2.1 确认应答2.2 超时重传 3. 连接保障机制3.1 三次握手建立连接3.2 四次挥手断开连接3.3 TCP状态转换过程 4. 传输效率保障机制4.1 滑动窗口4.2 快速重传 5. 控制机制5.1 流量控制5.2 拥塞控制 6. 应答机制6.1 延时应答6.2 捎带应答 7. 面向字节流7.1 缓冲区7.2 粘包问题 8. 异常情况 TCP协议也称“传输控制协议”(Transmission Control Protocol)其作用是要对数据的传输进行一个详细的控制。 1. TCP协议段格式 仔细阅读上图我们能够获得以下内容 源端口号/目的端口号表示数据是从哪个进程来到哪个进程去; 4位TCP报头长度表示该TCP头部有多少个32位bit(单位为4字节)则TCP头部最大长度是15 * 4 60字节; 6位标志位 URG紧急指针是否有效ACK确认号是否有效也称应答报文接收端返回给发送方表示是否接收到数据PSH提示接收端应用程序立刻从TCP缓冲区把数据读走RST对方要求重新建立连接我们把携带RST表示的称为复位报文段SYN请求建立连接我们把携带SYN标识的称为同步报文段FIN通知对方本端要关闭了我们称携带FIN标识的为结束报文段 16位校验和发送端填充CRC校验接收端校验不通过则认为数据有问题此处的校验和不光包含TCP首部也包含TCP数据部分 16位紧急指针标识哪部分数据是紧急数据 32位序号/32位确认号、16位窗口大小下文将进行详解
接下来我们将围绕TCP协议的特性来对其中的一些核心机制进行分析
2. 可靠传输保障机制 对于TCP来说它被创建的初心就是用来解决“可靠传输”的问题。网络通信过程是复杂的无法确保发送方发出去的数据100%能够到达接收方。此处可靠性只能“退而求其次”只要尽可能的去进行发送了发送方能够知道对方是否收到就认为是可靠传输。 那么又有哪些机制被用来保障可靠传输的进行呢
2.1 确认应答
TCP将每个字节的数据都进行了编号即为序列号。 接收端接收到数据后会给发送端返回一个ACK(应答报文)每一个ACK都带有对应的确认序列号来告诉发送端我已经收到了哪些数据下一次你从哪里开始发送。
注应答报文中的确认序列号是按照发送过去的最后一个字节的序号再加1来进行设定的 同时如果当前报文是应答报文此时报头中ACK这一位就是1 2.2 超时重传 超时重传是确认应答的补充如果一切顺利通过应答报文就能告诉发送端当前其发送的数据是否已成功收到。但是网络上也存在着“丢包”的情况如果数据包丢了没有到达接收端接收端自然也没有ack报文返回给发送端这个时候就需要超时重传了。 发送方如果一段时间内没有收到ack应答报文就会视为是丢包了从而触发重传把刚才的包再传一次
不过丢包不一定是发的数据丢了还可能是ack丢了 以上两种情况都会触发超时重传
注超时是会重传但重传也不是无限的重传它遵守以下规则
重传次数是有上限的重传到一定程度还没有ack就尝试重置连接如果重置也失败就会直接放弃连接重传的超时时间阈值也不是固定不变的随着重传次数的增加而增大(重传频率越来越低)
补充: 为什么网络中会出现丢包 网络中的通信使用到的通信设备如路由器/交换机不单单只用于两台主机之间的通信还需要提供给很多的主机进行使用。 因此整个网络中就可能存在某个路由器/交换机在某个时刻突然负载量很高短时间内有大量的数据包要经过这个设备转发同时又因为一台设备能够处理的数据量是有限的很可能瞬间的高负载超出了这台设备能够转发的数据量极限此时多出来的部分就无了就被设备丢包了。 3. 连接保障机制
对于TCP协议来说它是有连接的其需要连接管理机制来保障其正常进行即“三次握手四次挥手”
3.1 三次握手建立连接
在之前介绍过的TCP套接字编程文章链接代码中客户端执行这样一段代码
socket new Socket(serverIp, serverPort); 上述操作就是在建立连接但只是调用socket api真正连接建立的过程是在操作系统内核中完成的 那么内核又是怎样完成上述的“建立连接”过程的呢–通过“三次握手”
下图是“三次挥手”的简化流程图 在上述过程中第一次交互一定是客户端主动发起的。
其中syn是一个特殊的TCP数据报 没有载荷不会携带应用层数据但是会带有TCP报头等 六个标志位中的SYN为1 客户端先向服务器发起连接请求syn服务器在收到syn之后会返回ack(确认应答)表示我已经收到连接请求接下来服务器还会返回syn这个syn意思就是我接受你的连接我也愿意和你建立连接之后客户端接收到syn后再向服务器发送ack确认应答表示我也接收到你的回复了 所谓的建立连接过程本质上就是通信双方各种给对方发起一个syn各种给对方回应一个ack!
注: 虽然第一次握手客户端已经把自己的信息告诉给服务器了但是需要等所有的握手环节完成服务器才会最终保存客户端的相关信息。
进行三次握手的意义
三次握手可以先针对通讯路径进行投石问路初步的确认通信链路是否畅通(可靠性的前提条件)三次握手也是在验证通信双方的发送能力和接收能力是否正常服务器无法判断自身发送能力是否正常所以需要客户端返回ack进行判断三次握手的过程中也会协商一些必要的参数通信是客户端服务器两方的事情需要两方同时配合其中的有些内容要保持一致
3.2 四次挥手断开连接
断开连接的本质目的就是为了把对端信息从数据结构中删除掉或释放掉对此内核中通过“四次挥手”来断开连接 在四次挥手中第一次中断请求可以由客户端主动发送也可以由服务器主动发送通过调用socket.close()触发fin数据报一方在接受到fin后向对端发送ack应答报文以及fin数据报表示我同意与你断开连接对端接受到ack和fin后返回ack表示已经接收到同意断开连接的信息 如果当前处于结束报文段六个标志位中FIN为1 注: 在四次挥手中
调用socket.close() 就会触发FIN(FIN也是内核负责完成)如果进程直接接受也会触发FIN关闭socket文件也会触发FIN
下图是TCP建立连接和断开连接的详细过程图 三次握手和四次握手之间有相似之处也有不同之处
相似之处都是通信双方各自给对方发起一个syn/fin,各自给对方返回一个ack不同之处三次握手中间两次一定能合并四次挥手则不一定三次握手必须是客户端主动而四次挥手客户端/服务器都可以主动。
3.3 TCP状态转换过程
下图为TCP状态转换过程的汇总图 可以与上述TCP建立/断开连接的过程图结合分析 LISTEN: 表示服务器这边已经创建好了serverSocket并且完成了端口号绑定(手机开机了信号良好随时可以给我打电话)ESTABLISHED: 客户端和服务器连接已建立完毕(三次握手握完了); CLOSE_WAIT: 表示接下来代码中需要调用close来主动发起fin并且在收到对方的fin之后进入CLOSE_WAIT状态(谁被动断开连接谁进入CLOSE_WAIT状态);TIME_WAIT: 表示本端给对方发起FIN之后对端给本端也发送了FIN此时本端进入TIME_WAIT给最后一个ACK的重传留有一定时间防止最后一个ACK丢包(谁主动断开连接谁进入TIME_WAIT状态);
4. 传输效率保障机制
4.1 滑动窗口
在上述确认应答的机制下TCP的可靠性得到来保障但也因此降低传输效率 确认应答机制下每次发送方收到一个ack才会发下一个数据导致大量的时间都消耗在等待ack上了此处等待消耗的时间成本是非常多的 TCP希望保证可靠传输的前提下能够让效率尽量高点让消耗的尽可能少点。对此就引入了滑动窗口如下图所示 滑动窗口的本质就是批量传输数据。之前发了一个数据需要等待ack再发下一条数据现在是连续发了一定数据后统一等一波ack把多次请求的的等待时间使用同一份时间来等待减少了总的等待时间。 由上图可知数据是被批量传输出去的传输出这四份数据之后就等待ack暂时不传了其中白色区域(不需等待ack能够批量传输的最大数据量)被称为“窗口大小”
批量发了四个数据就会对应有四个ack此时四个ack也不一定是同时到达而是有先有后等到返回一个ack后就可以继续往后发送数据了窗口向右快速移动直观上呈现一种“滑动”的效果故上述过程就被称为滑动窗口。
注: 滑动窗口中当然也有确认应答只不过是把等待策略做了调整转成批量发送了批量的前提是短时间需要发很多数据如果发的数据很少此时滑动窗口滑不起来就退化成了确认应答。 4.2 快速重传
在滑动窗口中出现丢包要如何进行重传这里分两种情况讨论
情况一: 数据包已经抵达ACK被丢了 这种情况下部分ACK丢了并不要紧可以通过后续的ACK进行确认(后续的ack能够确认之前的数据都收到了)
情况二: 数据包直接丢了
这种情况就必须需要重传了对此我们使用快速重传机制来进行重传 在上述重传的过程中整体的效率是非常高的这里的重传做到了“针对性”的重传哪个丢了就重传哪个。整体的效率没有额外损失的就把这种重传称为“快速重传”。
5. 控制机制
5.1 流量控制
接收端处理数据的速度是有限的如果发送端发的太快导致接收端的缓冲区被打满这个时候如果发送端继续发送就会造成丢包继而引起丢包重传等一系列连锁反应。
因此TCP支持根据接收端的处理能力来决定发送端的发送速度这个机制就叫做流量控制。 接收端将自己可以接收的缓冲区大小分入TCP首部中的“窗口大小”字段通过ACK端通知发送端(窗口大小字段越大说明网络的吞吐量越高)接收端一旦发现自己的缓冲区快满了就会将窗口大小设置成一个更小的值通知给发送端发送端接受到这个窗口之后就会较慢自己的发送速度如果接收端缓冲区满了。就会将窗口设置为0这时发送方不再发送数据但是需要定期发送一个窗口探测包触发ack若查询窗口非0缓冲区又可以使用了发送方就可以继续发送了。
5.2 拥塞控制
虽然TCP有了滑动窗口这个大杀器能够高效可靠的发送大量的数据但是如果在刚开始阶段就发送大量的数据任然可能引发问题因为网络上有很多的计算机可能当前的网络状态就已经比较拥堵在不清楚当前网络状态下贸然发送大量的数据对设备来说很可能就是雪上加霜。
对此TCP通过拥塞控制机制来解决上述问题: 如果按照某个窗口大小发送数据之后出现丢包就视为中间路径存在拥堵就减小窗口大小如果没出现丢包就视为中间路径不存在拥堵就增大窗口大小 那么这个拥塞控制具体是怎么把这个窗口大小给试出来的具体如下图所示 慢启动刚开始传输的数据速率是比较小的采用的窗口大小(拥塞窗口)也就比较小此时网络拥堵情况未知不能一上来就传大量数据指数增长如果上述传输的数据没有出现丢包说明网络还是畅通的就要增大窗口大小此时增大方式是按照指数来增长的 (由于使用慢启动开始的时候窗口大小非常小也有可能网络上本身就很通畅通过指数增长可以让上述的窗口大小快速变大这样就可以保证传输的效率了)线性增长指数增长也不会一直持续的保持可能会增长太快一下就导致网络拥堵。这里引入一个“阈值”当拥塞窗口达到阈值之后此时指数增长就转变为线性增长。线性增长能够使当下的窗口持久的保持在一个比较高的速率并且也不容易一下就造成丢包乘法减小线性增长也是阈值在增长积累一段时间之后传输的速度可能太快此时还是会引起丢包。一旦出现丢包就把拥塞窗口重置为较小的值回到最初的慢启动过程(之后又要重新指数增长)并且这里也会根据刚才丢包时的窗口大小重新设置指数增长到线性增长的阈值。
拥塞控制归根结底还是TCP协议想尽可能快的把数据传输给对方但是又要避免给网络造成太大压力的折中方案。
6. 应答机制
6.1 延时应答
当接收数据的主机立刻就返回了ack应答接下来返回的窗口可能就比较小如下 假设接收端缓冲区为1M,一次收到了500K的数据如果立刻应答返回的窗口就是500K,但实际上可能处理端处理的速度很快10ms之内就把500K数据从缓冲区消费掉了这种情况下接收端处理还远没有达到自己的极限即使窗口再放大一些也能处理过来。 对此如果接收端稍微等一会再应答比如等待200ms再应答那么这个时候返回的窗口大小就是1M,这样的话我们的传输效率也能有所提高
所以接收方在收到数据之后不会立即返回ack而是延时一会之后再返回ack等了这一会相当于给接收方的应用程序这里腾出更多的时间来消费这里的数据这就是延时应答。
注: 窗口越大网络吞吐量就越大传输效率就越高。我们的目标就是在保证网络不拥塞的情况下尽可能提高传输效率。
6.2 捎带应答
在延迟应答的基础上引入了捎带应答机制来提升传输效率 捎带应答就是尽可能的把能合并的数据包进行合并从而起到提高效率的效果 就如我们“三次握手”中的ack应答捎带上了syn一起返回给了发送端握手是打招呼而打招呼是一个没有实际意义的数据报是没有载荷数据的 7. 面向字节流
7.1 缓冲区
在TCP套接字网络编程中我们通过创建一个TCP的socket同时在内核中创建一个发送缓冲区和一个接收缓冲区来实现面向字节流编程在此基础上
调用write时数据会先写入发送缓冲区中如果发送的字节数太长会被拆分成多个TCP的数据包发出如果发送的字节数太短就会先在缓冲区里等待等到缓冲区长度差不多了或者其它合适的时机发送出去接收数据的时候数据也是从网卡驱动持续到达内核的接收缓冲区应用程序可以调用read从接收缓冲区拿数据
注TCP的一个连接即有发送缓冲区也有接收缓冲区那么对于这一个连接既可以读数据也可以写数据这个概念就叫做全双工。
7.2 粘包问题
粘包问题中的包指的是“TCP载荷中的应用数据包”结合之前讨论过的内容来进行理解tcp传输的数据到了接收方之后接收方要根据socket api 来read出来read出来的结果就是应用层数据包但由于整个read过程非常灵活可能会使代码中无法区分出当前的数据从哪到哪是一个完整的应用数据包 粘包问题不是TCP独有的问题只要是面向字节流的都有同样的问题而解决问题的关键就是要明确包之间的边界
通过特殊符号作为分割符见到分割符就是视为一个包结束了指定出包的长度比如在包开始的位置加入一个特殊的空间来表示整个数据的长度 对应的UDP就没有这个问题。UDP传输的基本单位是UDP数据报在UDP这一层就已经分开了。只要约定好每个UDP数据报都只承载一个应用层数据包就不需要额外的手段来进行区分了。 粘包问题是TCP引起的但是TCP本身不会解决需要程序员写代码在应用层逻辑的时候自己去进行处理
8. 异常情况
在出现以下异常情况时会有对应的处理方式 进程终止/机器重启进程终止会释放文件描述符仍然可以发送FIN进行正常的四次挥手结束和正常关闭区别不大 机器掉电/网线断开 若断电的是接收方发送方就会突然发现没有ack了就要重传重传几次后发现还是不行TCP就会尝试“复位”连接相当于清除原来的TCP中的各种临时数据重新开始 此时上述RST为1若重装了还不行则单方面放弃连接 若断电的是发送方则接收方需要区分出发送方是挂了还是好着但暂时没发。对此接收方一段时间之后若没有接收到对方的消息就会触发“心跳包”来询问对方的情况(心跳包是不携带应用层数据的特殊数据包具有周期性)若判断对方没有心跳此时本端也就会尝试复位并且单方面释放连接。