网络流量处理中的协议解析六: 执行器

执行器

rust 中有很多异步执行环境。但是异步执行环境有一个问题。它有"传染性",如果一个函数是异步的,那么它的所有调用者都必须是异步的。在前面的流量处理模型并不是异步的。所以为了不至于把协议解析部分的异步影响到流量处理模型,我们需要一个自己的执行器。这个执行器把异步操作封装起来,然后在流量处理模型中使用。尽量不影响使用者的习惯和模型,是一个库的修养。

rust 的执行器简单来说类似于前文所讲的c语言的状态机驱动函数。如果一个future返回了 Ready ,说明future已经完成了,需要执行下一步。如果一个future返回了 Pending ,说明future还没有完成,需要等待下一次调用。因为我们不需要复杂的异步运行时,所以这里的执行器只需要控制好future的返回值即可。代码如下:

rust 复制代码
    let waker = dummy_waker();
    let mut context = Context::from_waker(&waker);
    match Pin::as_mut(parser).poll(&mut context) {
        Poll::Ready(Ok(())) => {
            self.c2s_state = TaskState::End;
            Some(Ok(()))
        }
        Poll::Ready(Err(())) => {
            self.c2s_state = TaskState::Error;
            Some(Err(()))
        }
        Poll::Pending => None,
    }

这样,内部是异步,外部是同步。每到来一个包,执行器就执行一次future,也就是解码器。外部不需要异步操作。也就是在同步代码中可以调用执行器:

rust 复制代码
    loop {
        pkt = get_packet();
        task.run(pkt);
    }

当然,要获取解码结果。需要提前设置回调函数。解码过程中就会触发回调函数。

解码器

所有的这些工作,都是为了解码器。因为需要同时处理大量的链接,解码过程中是不能等待后续数据包的。所以解码器是一个future,也就是异步函数。当后续数据还没有到来时,解码器返回Pending,暂时挂起。执行器得到Pending后,不会认为这个链接的解码已经结束,而是继续处理下一个链接。

但这种异步调用的复杂性都被rust的future机制封装起来了,解码器的实现关注解码器的实现即可。完全可以按照同步的模式来写,例如SMTP协议的解码器的部分代码:

rust 复制代码
    loop {
        let (line, seq) = stm.readline_str().await?;

        if line == "\r\n" {
            return Ok((boundary, te));
        }
    }

这就是读取重组后的头部数据的过程。可以看到,它并没有关心数据没有到来的情况。如果当前的数据包并没有完整的数据,解码器中也不需要对此进行判断,和退出。它完全按照同步的过程在执行解码。直到读取到头结束为止。唯一的区别就是它的读取数据函数式一个异步函数。末尾加了await关键字。

每一个await都会触发一次future的调用。如果当前的数据包没有完整的数据,那么await会返回Pending,解码器会被挂起。执行器会继续处理下一个数据包。当数据包到来时,解码器会被唤醒,继续执行。直到读取到头结束为止。

这样,我们就可以把协议解析的工作交给执行器来处理。执行器会自动处理异步的情况。使用者只需要关注解码器的实现即可。而且解码器的过程变得简单容易理解。

从最开始的c语言中的大循环中记录状态,到c语言中用状态机驱动,再到rust的future机制,再到现在的解码器,过程越来越简单,最终我们以同步的流水账式的代码来实现了异步的解码过程。

参考: protolens@gitee protolens@github

相关推荐
2501_915106329 小时前
抓包抓到乱码或压缩字节怎么解析,TraceEagle五种查看模式和一键解码
网络协议·计算机网络·网络安全·ios·adb·https·udp
情 九9 小时前
MCP 实战 06:把 HTTP 接口接成工具,让 AI 帮你查数据
人工智能·网络协议·http·mcp
Da Da 泓11 小时前
五子棋 Web 端测试用例报告
前端·网络·websocket·网络协议·测试用例·项目
万联WANFLOW18 小时前
异地组网速度忽快忽慢到底怎么回事?直连与中继的判断方法和处理步骤
运维·网络·网络协议·p2p
步行cgn21 小时前
HTTP 请求报文结构详解:请求行、请求头、请求体各自的作用
网络·网络协议·http
OpenLoong 开源社区1 天前
打破 NAT 限制,零侵入跨网络通信:基于 WebRTC 的透明 TCP 隧道跨网络通信方案
网络协议·tcp/ip·开源·webrtc·openloong开源社区
从琳开始9891 天前
从Socket到UDP回显服务器:Java网络编程完整指南
java·网络·网络协议·udp·java-ee
明天也要努力学习1 天前
HTTP 协议的基本格式和 fiddler 的用法
网络协议·http·fiddler
Tel199253080042 天前
温度湿度信号转WiFi/MQTT/Modbus TCP采集模块 无线传输
网络·网络协议·tcp/ip·工业自动化·工控设备
lazy H2 天前
【计算机网络】第 13 篇:NAT 和端口映射是什么?为什么本地服务外网访问不了?
java·网络·网络协议·学习·计算机网络·408