做网站的公司有哪些,专业做冻货的网站,aspcms 网站统计,新手学百度竞价要多久文章目录 可靠传输机制1.确认应答2.超时重传2.连接管理1.三次握手2.四次挥手 传输效率1.滑动窗口2.流量控制3.拥塞控制4.延时应答5.捎带应答 面向字节流粘包问题 TCP异常情况 可靠传输机制 可靠性#xff1a;即发送方知道数据是发送成功了#xff0c;还是失败了。 1.确认应答… 文章目录 可靠传输机制1.确认应答2.超时重传2.连接管理1.三次握手2.四次挥手 传输效率1.滑动窗口2.流量控制3.拥塞控制4.延时应答5.捎带应答 面向字节流粘包问题 TCP异常情况 可靠传输机制 可靠性即发送方知道数据是发送成功了还是失败了。 1.确认应答
确认应答是TCP实现可靠传输最为核心的机制。 主机A给主机B发送消息B收到之后返回一个应答报文ACKA收到应答报文后就知道第一条消息发送成功了于是继续发第二条消息… 确认应答即应答报文也称为ACK报文。 序号类似数据11000等TCP是面向字节流的这里的11000这类数字就是1~1000个字节每个字节都编有序号。因为字节编有序号所以避免了发送的数据乱序的问题 。 TCP字节序号是依次累加的第一条数据字节序号11000第二条数据就是10012000。由于这1000个字节都属于一个TCP报文所以每个TCP数据报头只存当前数据的第一个序号比如第二条数据的TCP报文里存1001再根据 TCP报文长度就知道这条数据是1001~2000。 确认序号每个确认应答都带有数字确认应答1001这类数字就是确认序号而确认序号只有应答报文拥有ACK标志位为1表示为应答报文ACK标志位为0表示不是应答报文。确认序号表示成功收到哪些数据下一条数据从哪里开始发。确认序号返回的是收到当前数据最后一个字节序号的下一个序号列如收到11000个字节数据返回1001表示1001之前的数据都收到了于是下一条消息是从编号为1001的位置开始发即10012000。
2.超时重传
丢包分为两种情况一是发送数据丢了二是返回的ACK丢了。为了解决丢包问题TCP引入了超时重传机制在丢包的情况下重新发送一份相同的数据。如何判断丢包呢TCP引入了一个时间阈值发送方传输一个数据在一个规定的时间内如果未收到ACK不管三七二十一都表示为丢包了进行重传。 数据丢包主机A发送的数据丢包了在隔了一定的时间后未收到主机B发来的确认应答则会再次传输1~1000的数据 ACK丢包可以发现主机B收到了两次1~1000这个数据TCP会根据这种重复数据进行去重利用TCP的接收缓冲区进行去重。这个缓冲区相当于一个阻塞队列当主机B读到了主机A发送的数据主机B把这个数据放入这个阻塞队列中再根据数据的序号排序、去重如果序号重复则丢弃后来的数据。 超时重传可能会重传几次当重传次数达到一定的次数时TCP会尝试重连如果重连失败则彻底断开连接。重传的时候第一次重传时间和第二次时间间隔不一样重传次数越多时间间隔越大。 2.连接管理
在正常情况下TCP要经过三次握手建立连接通过四次挥手断开连接所谓连接本质上是通信双方互存储了对方的信息管理则是描述了连接如何连接和断开。
1.三次握手 举一个比较形象的列子A先发一条消息B收到后并响应同时B再发送一条消息给AA收到后并响应。 三次握手本质上是四次交互我们形象的把每次通信比喻成一次握手。通信双方各自要发送一个“建立连接”的请求并各自返回对方一个ACK应答报文。由于主机B的响应和发送新消息好啊确认哈…这两次交互的时间非常近于是就把这两次交互合并为一次也就成了三次握手并且这两次合并是必须的因为每次通信都需要封装分用两次封装分用肯定要比一次封装分用的成本高。 问题四次合成了三次那么直接合成两次可以完成吗 答显然是不能的。当主机A发送了一条消息明天一起吃饭主机B响应并发送新消息好啊确认哈一起吃饭别放鸽子。此时主机A知道了主机B同意明天一起吃饭但是主机B并不完全确定主机A会不会放鸽子。那么明天A和B可能也就吃不成饭了也就意味着主机A和主机B连接建立不了 三次握手的意义一是建立通信双方的认同保存对方的信息二是为了验证通信双方各自的发送和接收是否正常三是在每次交互会夹带一些重要信息来协商一些重要的参数。 客户端主动给服务器发起的建立连接请求称为“SYN”/同步报文段synchronize对应着TCP报文结构里的“SYN”然后服务器进行响应返回“SYNACK”说明这条交互既是同步报文段又是确认应答报文段最后客户端返回一个“ACK”应答报文。 TCP连接有11种状态分别是LISTEN、SYN_SENT、SYN_RECEIVED、ESTABLISHED、FIN_WAIT_1、FIN_WAIT_2、CLOSE_WAIT、CLOSING、LAST_ACK、TIME_WAIT和CLOSED。 建立连接时的状态 LISTEN表示服务器端的某个SOCKET处于监听状态可以接受客户端的连接 SYN_SENT表示在发送连接请求后等待匹配的连接请求 SYN_RECEIVED表示在收到和发送一个连接请求后等待对连接请求的确认 ESTABLISHED表示已经建立了连接可以进行数据传输上图中客户端和服务器都有这个状态。 CLOSED表示TCP连接已经关闭 。 2.四次挥手
挥手和握手一样都是形象的比喻。四次挥手也是通信双方各自对对方发送一个断开连接的请求再各自发送一个响应。 问题中间两次是否能合并到了你呢 答显然不行三次握手的两次交互之所以可以合并是因为这两次交互是同一时机这一操作是纯内核操作是我们感受不到的当服务器收到syn后会立即返回ack而四次挥手则不同这两次交互是不同时机当主机A的应用程序执行到socket的close方法时会触发FIN结束报文段服务器接收到FIN后内核会立即返回ACKFIN是人为发送的而ACK是由系统内核控制的当主机B的应用程序执行到socket的close方法时也会触发FIN应用程序执行到close方法前可能要经过很多道其他的程序代码于是和ACK的时机相隔太久也就不能合并为一次交互。 断开连接时的状态 CLOSE_WAIT表示被动断开连接一方等待FIN报文 TIME_WAIT表示主动断开连接的一方收到了对方的FIN报文但是还没有发送ACK报文 TIME_WAIT的意义 TIME_WAIT状态站在客户端视角认为已经断开连接了但是此时TIME_WAIT会让连接状态继续保留因为最后一个ACK还没有发出去如果最后一个ACK丢包服务器会进行超时重传重新传一个FIN客户端再重新发一个ACK因此TIME_WAIT状态保留连接状态一定时间就是为了有能力进行重传如果重传的还是丢了时间也到了那么就认定为最后ACK没丢直接断开连接。 TIME_WAIT保留时间为2MSLMax Segment Life报文最大生存时 间2MSL表示为互联网上两个节点之间数据传输消耗的最大时间这个时间通常为60s。 传输效率
1.滑动窗口 活动窗口的目的是为了在可靠性传输的基础上提高传输效率。 基础的确认应答机制主机A发一次数据主机B只要收到一条数据就返回一个ACK而主机A此时在没有收到ACK的时候需要进行等待才能发送下一条数据每一次发送数据都要等一次这就造成了不少的等待时间。 加入活动窗口后的确认应答机制主机A不再需要等待第一条数据的ACK可以一次性发送多条数据再使用一份等待时间来等待一组数据返回的多个ACK这就减少了多条等待ACK的时间。 下图是主机A一次性批量发送四条数据主机B再批量返回四个ACK收到一条数据就返回一条ACK依次类推只是说主机A不需要等第一个ACK就可以连续发4条数据。 把不需要等待就可以发送的最大的数据量就称为“窗口大小”上图这个“窗口大小”为4000。 发送一个窗口大小的数据后主机A并不是要等这一个窗口大小的ACK全部返回了才继续发送下面的数据而是主机B接收到一条数据就返回一条ACK主机A收到一个ACK就发一条数据这样就保证了等待的ACK永远都是4条窗口大小处理的数据永远都是4条而不是处理一条就没事做了。 举个例子比如一个人有4台电脑一台电脑可以刷一门课同时只能刷4门课需要刷满10门课此时“窗口大小”就是4。当我刷完一门课后手上正在刷的课为3门那么就有一台电脑是空闲状态于是我就可以再找一门课继续刷一直保持刷4门课的状态。相当于用1门课的时间刷了4门课用最少的时间刷完10门。 每次刷完一门课就立即开始下一门窗口大小始终未变但是课程变了。类似于下图本来需要等10015000的ACK但是收到了2001的ACK说明2001之前的数据已经被确认此时可以立即发送50016000的数据等待的ACK范围就成了2001~6000这种现象看起来就像是在滑窗口于是就形象的比喻成滑动窗口 滑动窗口情况下丢包了怎么解决 ACK丢了不需要做出任何处理因为有确认序号当返回2001的ACK说明2001之前的数据都到达了2001包含了1~2000的数据序号。 数据包丢了下图显示当10012000的数据丢了主机B返回的是1001的ACK意思是索要主机A1001开头的数据主机A连续发送多条数据后收到的依旧是1001的ACK这时主机A就会发送10012000的数据。当主机B成功收到10012000的数据后由于主机A之前已经发送20017000的数据并且主机B成功收到了于是这次返回的是7001的ACK说明7001之前的数据都收到了包含10012000的数据也就意味着主机A下次发送的数据是从7001开始。假设40015000也丢包了此时是返回的ACK是5001而不是7001即使主机A已经把数据发送到了7000。总结丢哪个包就索要哪个包的数据。 这种重传方式称为“快速重传”表示只重传丢失的数据。 2.流量控制 滑动窗口提高了传输效率可是窗口也不能无限大因为接收方处理能力有限。流量控制的意义是为了根据接收方的处理能力来控制发送方的传输效率。 那么如何衡量接收方的处理能力呢 可以根据接收方的接收缓冲区剩余大小来判断比如传输10个接收缓冲区还剩下20个说明下次可以传输20个或者30个接收方都能处理过来。 比如主机A给主机B发送了一条数据B就算一下接收缓冲区剩余空间再把这个结果通过ACK返回给AA根据这个结果来决定下次发送的窗口大小是多少是连续发10个还是20个。 TCP报文结构里有16位窗口大小即默认为64kb而TCP为了让窗口大小可以更大在选项中引入了窗口大小的扩展因子比如扩展因子里是2表示64kb左移2位即256kb。 上图显示第一次A传输了11000的数据B返回1001ACK接收缓冲区剩余大小为3000A再次发送10014000的数据B依次返回三个ACK 当B的接收缓冲区为0了A机会进行等待在等待时间A会发送一个窗口探测报文来询问B的接收缓冲区是否有空余。 3.拥塞控制 流量控制和拥塞控制共同决定发送方的窗口大小。 流量控制表示接收方的处理能力 拥塞控制表示传输过程中的中间节点的处理能力中间节点路由器运营商等。 中间节点的测量通过实验来测试出一个合适的值。比如先发少量的数据探探路摸清当前的网络拥堵状态再决定按照多大的速度传输数据 下图表示实验中间节点的窗口大小第0轮。窗口大小为1没有丢包就扩大窗口第二次就为2…以指数增长;当增长速率达到阈值时变成线性增长当丢包了也就是遇到网路拥堵窗口大小一下子变为一个很小的值再重新按指数增长线性增长此时的增长速率阈值为上次网路拥堵的值除2…依次类推直到找到不是网络拥堵的瓶颈并且是一个最大的值 。拥塞窗口会根据当前网络环境一直动态的调整。 4.延时应答 延时应答收到数据后不是立刻返回ACK而是稍等再返回。 在滑动窗口上进行改进比如主机A第一次发送数据B的原本接收缓冲区大小为1MB计算后立即返回的ACK窗口大小为500kb那么下次A传输的数据就是500kb但是如果要是稍等再返回ACK在这个稍等的时间内主机B把这个500kb给消费掉那么返回的窗口大小就为1M下次A就可以发1M的数据从而提高传输效率。 上图显示实际上延时应答采取的方式为在滑动窗口下ACK不再每一条数据都返回比如上图隔一条返回一个ACK。 5.捎带应答 在延迟应答的基础上我们发现很多情况下客户端服务器在应用层也是 “一发一收” 的。意味着客户端给服务器说了 “How are you”服务器也会给客户端回一个 “Fine, thank you”因为TCP存在延时应答ACK等了一会那么这个时候ACK就可以搭顺风车和服务器回应的 “Finethank you” 一起回给客户端 由于内核返回的ACK存在延时应答于是等待这时候应用层发了一条数据刚好和延时应答后返回的ACK时机相同于是这两次合并为一次。 面向字节流
粘包问题 接收缓冲区实际上是把收到的数据都放在一起由于TCP的字节流的但是应用层序read读取时可以一次read一个字节或多个字节读到哪里才算是一个完整的应用层数据报呢这就导致可能read读取到的是半个数据报或是多个数据报。就好比下图假设下图都是主机B返回的数据主机Aread读取时一次读8个字节读取到了“abcdefgh”这种情况就叫粘包问题 解决方案在应用层约定每个数据报之间用什么分隔符区分比如用“\n或者约定每个数据报的长度。 TCP异常情况 进程崩溃进程终止会释放文件描述符仍然会完成四次挥手。和正常关闭没有什么区别。 主机正常关机和进程崩溃一样。 主机掉电/网线断开 接收方掉电发送方接收不到ACK超时重传几次会尝试重置连接最后彻底放弃连接。发送方掉电接收方收取不到数据于是会周期性的发送一个消息确认对方是否正常工作这种操作称为“心跳包”。通过“心跳包”来确认通信双方是否正常。 进程崩溃进程终止会释放文件描述符仍然会完成四次挥手。和正常关闭没有什么区别。 主机正常关机和进程崩溃一样。 主机掉电/网线断开 接收方掉电发送方接收不到ACK超时重传几次会尝试重置连接最后彻底放弃连接。发送方掉电接收方收取不到数据于是会周期性的发送一个消息确认对方是否正常工作这种操作称为“心跳包”。通过“心跳包”来确认通信双方是否正常。