ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Linux之TCP<2>

Linux之TCP<2> 1.理解TCP报头TCP报头的本质:结构体1.TCP报头和有效载荷分离???(不包括选项这里先不说)报头的长度是固定的2.分用问题存在目的端口号为什么TCP有报头长度,但是没有有效载荷长度???对于TCP叫做可靠性协议的正确认识可靠性核心定义TCP 要保证我方发出的数据能够得到对方应答确认通过确认应答机制保证历史发送的数据100% 交付到对端的内核缓冲区。客户端要怎么知道服务器端有没有收到报文只有当客户端收到服务器给他的报文的时候才确定上面那条报文收到了当然要是没有收到报文也会有下面两种情况我方发送出去的报文在路上丢失数据包损毁、网络丢包压根没有抵达服务端。服务端返回的 ACK 确认报文在路上丢失服务端明明收到数据了但是回执报文网络丢包回不到客户端。对客户端来说这两种现象表现完全一样收不到 ACK客户端区分不开到底是数据丢了还是 ACK 丢了。超时重传机制客户端发送报文时会启动超时计时器,超过deadline就会触发重传。如果计时器到期之前收到了对应的 ACK 确认计时器清零万事大吉。如果超时时间耗尽依旧没有收到 ACK触发超时重传把原来的数据报文重新发送一遍。总结可靠性确认应答 保证数据一定送达对方。这种说法不准确。因为网络本身是不可靠的数据包可能在传输过程中丢失、损坏或延迟。无论协议怎么设计都无法做到 “数据一定能到达对方”。真正能做到的是如果数据到达了发送方能收到确认如果数据长时间没有得到确认发送方可以判定本次发送异常并采取重传等措施。所以确认应答更准确的意义是让发送方获得一次明确的反馈而不是一直处于未知状态当前没有收到报文要不要继续等待要不要重新发送确认应答机制就是为了解决这个问题。它让发送方在限定时间内得到一个明确状态有以下几种情况情况一对方收到数据接收方收到报文后回复 ACK。发送方收到 ACK 后可以确定本次数据已经被对方接收。于是发送方可以继续发送下一段数据或释放本次发送缓冲区。情况二对方没有收到数据如果报文在网络中丢失接收方自然不会回复 ACK。发送方超时后仍未收到 ACK就会知道本次发送结果不确定需要重传。此时发送方不是盲目认为 “对方一定没收到”而是根据超时机制做出一个合理判断并触发重传。情况三对方收到了但 ACK 丢失这时发送方仍然收不到 ACK会触发超时重传。从结果上看发送方并不知道 “对方其实已经收到了”但这并不影响确认应答机制的价值。因为对于发送方来说它得到的仍然是一个确定结果超时未收到 ACK执行重传。而接收方收到重复数据后可以通过序列号识别并丢弃重复报文再回复 ACK。所以确认应答机制关注的不是 “每次都必须成功送达”而是无论网络情况如何发送方都能按照统一规则得到一个确定处理结果。按序投递TCP 通信协议层面 A、B 两端地位完全对等、双向对称两端都既能发也能收。在实际中TCP发送报文大多是以下这种情况一下子发很多,然后接收很多,不会是一条发一条收,这样的效率实在是太低了但是像这样发送可能会存在乱序问题---IP 网络报文走不同路由接收方收到报文顺序和发送顺序不一致。序列号 接收缓冲区乱序到达的报文不会直接交给应用先存缓冲区根据序列号对数据重新整理排序只有拿到连续完整字节流才按正确顺序交付上层应用。去重识别重复报文丢弃重复数据排序处理网络乱序保证上交应用的数据有序如果发回来的应答丢了,3001丢了,那么对方报文到底有没有全部收到呢????答案就是全部都收到了,因为确认序号4001,也就是表明前面的报文全部都是收到了确认序号 自己收到的序号 1确认序号 含义该序号之前的所有数据我收到了 seq: 1000 ack seq: 10011001 序号之前的所有数据我收到了为什么既要有序号,又要又确认序号因为有捎带应答的出现,提高效率捎带应答piggybacking如果没有两套字段收到数据 → 单独发一个纯 ACK 报文应答要发数据时再单独发数据报文。 来回多一次报文开销大效率低。TCP 设计应答信息不单独发报文直接 “捎带” 在自己要发送的数据报文中。报文里用seq放自己要发数据的编号报文里用ack放对对方数据的确认回执。 同一个 TCP 报文同时携带 “我方的数据” 和 “对对方的应答”不用额外发送纯 ACK 包减少报文数量提升网络传输效率。16位窗口大小我们知道 TCP 在内核中维护两套缓冲区发送缓冲区、接收缓冲区。接收缓冲区是接收方内核开辟的一块内存应用程序调用read()才会把数据从内核缓冲区拷贝到用户空间缓冲区的剩余容量是动态变化的。假设场景接收缓冲区总大小 4KB上层应用读取慢当前已经占用 3KB仅剩 1KB 空闲空间。 此时发送方还在持续发送大量数据。接收方缓冲区已满之后新来的数据无法存入内核缓冲区就会被直接丢弃。 数据包跨越网络传输之后被丢弃网络带宽白白消耗重传又会进一步拉低整体传输效率。但是如果要是接收方给发送方,告知它有剩余的缓存空间,那么也就是说会更好的控制发送报文,数据的时间TCP 引入流量控制机制接收方会在 ACK 报文中携带自己接收缓冲区的剩余可用大小这个值就是接收窗口 rwnd。 发送方拿到这个窗口大小就知道最多只能发送不超过窗口大小的数据不能一股脑疯狂发包。接收方,如何衡量自己的接收能力??看接收缓冲区中剩余空间的大小发顺丰如何得知对方的接收能力??将自己的接收能力,填写到应答报文的16位窗口大小中流量控制--可靠性效率标志位有这么多种报文,当然要对他来进行管理标志位是用来区分报文类型的ACK:确认序号是否有效。绝大多数 TCP 报文 ACK1只有连接建立的第一个 SYN 报文ACK 才为 0。ACK 有效时确认序号字段才具备意义用来回执已经收到的数据。SYN:主机 A客户端 ↔ 主机 B服务端第一次握手SYN 报文主机 A 发送SYN1报文向 B 发起连接请求携带自己的初始序列号 seq。比喻A“你可以做我女朋友吗我想和你建立连接”第二次握手SYNACK 报文主机 B 收到 SYN回复SYN1ACK1报文。 一方面回复同意建立连接 (SYN)另一方面对 A 的请求做确认应答 (ACK)。比喻B“可以什么时候开始我收到你的请求我也同意建立连接”第三次握手ACK 报文主机 A 收到 SYNACK回复纯ACK1确认报文确认收到 B 的同步请求。报文发送完成连接正式建立可以传输业务数据。比喻A“就现在我收到你的答复连接正式就绪”双方OS都会存在大量的连接,OS要管理这些连接---先描述在组织,存在链接结构体,这个结构体相对于UDP的更加复杂,建立链接时有成本的,时间空间通信之前,要先保证网络是通畅的---验证全双工FINTCP 是全双工A、B 双方各自都要关闭自己的发送通道所以需要 4 次报文交互。 主机 A主动关闭方主机 B被动关闭方第一次挥手FIN 报文主机 A 发送FIN1告诉 BA 这边不再发送新数据准备关闭自己方向的通道。比喻 A“我这边说完了我不发消息啦。”第二次挥手ACK 报文主机 B 收到 FIN回复ACK1确认。此时 A→B 方向关闭但 B 还可以继续给 A 发送剩余的数据。比喻 B“收到我知道你不发消息了不过我这边还有话要说。”第三次挥手FIN 报文等 B 把本机剩余数据全部发送完毕后B 发送FIN1通知 AB 也不再发送数据。比喻 B“我的消息也发送完了我也要结束对话。”第四次挥手ACK 报文主机 A 收到 B 的 FIN回复ACK1确认。B 收到 ACK立刻关闭连接。A 会等待TIME‑WAIT时间再释放本地资源防止最后这个 ACK 报文丢失保证 B 可以收到确认。比喻 A“好的到此结束。”基于上面的了解为什么是三次握手,四次挥手也可以是三次握手啊???这里其实是用到了捎带应答,--也就是说作为服务器端,别人向你发起连接,你在很多时候都是答应的,因为你是服务器,捎带应答可以提高效率而四次挥手是因为可能有一方要继续传输数据,不能中断不能立刻发出 FIN 关闭报文。
返回列表