IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 不可靠不重传的假 TCP -> 正文阅读

[网络协议]不可靠不重传的假 TCP

还是那个面试题:如何用 TCP 实现不可靠传输?… 本文有趣,黑科技,仔细看。

TCP 是"运营商友好"的。运营商依据 TCP 状态机能以任意粒度对 TCP 连接进行任意管控,包括不限于限速,整形,重置,计费,TCP 和运营商是互惠的。

UDP 像脱缰野马变幻莫测,运营商只能一刀切,比如高峰期给所有 UDP 流量仅 10 % 的资源份额。

让运营商看起来是 TCP,但实际上是 UDP,可以考虑做一个假 TCP 封装。

最简单的,把 IP 协议号从 UDP(17) 改成 TCP(6),复杂点就换个传输头,都可取。比如换头:
GitHub - marywangran/pseudotcp-tunnel

此外,各大厂也有各类冠以自研修饰的 XX 协议,它们有多么复杂自然不必多说,主要目的是卷。

我给一个 10 行代码实现的假 TCP,找到 Linux 内核 tcp_data_queue 函数,从注释处增加代码:

static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
{
        struct tcp_sock *tp = tcp_sk(sk);
        bool fragstolen;
        int eaten;

        if (sk_is_mptcp(sk))
                mptcp_incoming_options(sk, skb);

        if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq) {
                __kfree_skb(skb);
                return;
        }

        skb_dst_drop(skb);
        __skb_pull(skb, tcp_hdr(skb)->doff * 4);

        // 增加下列 if 语句 13 行代码,暂硬编码 5001 端口,只为 iperf 测试。
        if (inet_sk(sk)->inet_num == 5001 && after(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) {
                struct sk_buff *nskb;
                u32 n = TCP_SKB_CB(skb)->seq;
                if (!before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt + tcp_receive_window(tp)))
                        goto out_of_window;
                nskb = skb_copy_expand(skb, n - tp->rcv_nxt, 0, GFP_ATOMIC);
                if (likely(nskb)) {
                        skb_put_padto(nskb, n - tp->rcv_nxt + skb->len);
                        consume_skb(skb);
                        skb = nskb;
                        TCP_SKB_CB(skb)->seq = tp->rcv_nxt;
                }
        }

        tp->rx_opt.dsack = 0;

将这代码部署在接收端,事竟成。

意思是保证发送端 una 不断前推,不会收到 sack 和 dupack,也就不会重传。如下图:
在这里插入图片描述
简单说,收到空洞,空洞立即被填充,丢包补零不重传,这种粗暴策略意味着即使真发生乱序,数据也会被 0 填充掉。但简单啊。

看效果:
在这里插入图片描述
解释一下测试结果,为什么假 TCP 对丢包无感。

假 TCP 是有损传输,iperf 并不校验这种有损,所以即使结果带宽很大,有效的到达数据却随丢包率增加而减小。strace 观测 iperf 接收端实际接收到的数据:
在这里插入图片描述
这些 0 即被填充的 0,即有损传输的体现。丢包率越高,0 的比例越高。

结合优质高尚的编码可最大限度消除有损传输的质量伤害,还记得传皮鞋那个吗?参见:有损传输示例

再举一例。用有损传输方式接收一个 HTML 文档,会是一堆乱码吗?并不会。

若有数据丢失,至多丢失一些 HTML 标签和内容,HTML 标签封闭嵌套特点使标签自动补全变得可行且容易,最终依然可得到一个虽缺失部分内容但浏览器依然可展示的文档。

不仅如此,这些 0 还有妙用。通过分析一段时间内这些 0 的分布,绘制一幅拥塞画像是高尚的。
说说假 TCP 有什么用,到底哪里需要把 UDP 伪装成 TCP?

仅在接收端部署那 13 行代码,TCP 就五脏俱全了,这本就是一个真的 TCP,足以糊弄运营商的行为也就不能叫欺骗。除了不重传,TCP 的特性一样不少。

不重传意味着传输有损,收益是消除了重传时延,非常适合承载时延敏感的业务,如 VNC,流媒体。它适合传输任何 UDP 数据,以绕过运营商对 UDP 的一刀切管控,用这个协议搭建的隧道是通用,高尚的隧道。

两三事:

  • 常见的面试题,如何用 UDP 实现可靠传输,但不高尚。高尚的面试题应该是,如何用 TCP 实现不可靠传输。
  • TCP 的不可靠传输:TCP的不可靠传输
  • 搭建隧道时还在 TCP 和 UDP 中二选一吗?
  • 还在自研万行代码级的协议吗?本文只是个把戏,实际可以做得更好,比如给个窗口 Buffer,允许乱序的发生,Buffer full 了才补零。
  • 黑科技每周都有,你肯看,我就有。

周中有朋友问起假 TCP 的事,我说抽空写一篇。这种协议要看你想要多假,可以只封装个 TCP 头,但要更逼真,就要能让运营商设备识别 Session,这一步很重要,运营商正是因为容易识别 TCP Session,才视 TCP 为友好的。于是假 TCP 变得复杂… 反着做,在真 TCP 上做减法,把约束一个个卸掉,直到它足够假,也就假亦真时真亦假了。当然,三次握手要斟酌,对于长连接,这无关紧要,可对于短连接,重试成本低到是否可靠也同样无关紧要。不过我依然有办法连三次握手也优化掉,不过要下回分解。

浙江温州皮鞋湿,下雨进水不会胖。

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-08-19 19:37:39  更:2022-08-19 19:37:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 23:29:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码