Erlang:在不消耗套接字数据的情况下识别协议



我需要在Erlang中的单个侦听套接字上处理两个不兼容版本的协议。

不幸的是,协议升级设计不正确,因此新协议不是旧协议中的"升级协议"选项(切换到新协议或版本控制),而是纯TLS连接(旧协议是面向纯TCP请求-响应行的连接)。

现有的C实现使用recvmsg(MSG_PEEK)从连接开始嗅探几个字节,然后将套接字传递给其中一个处理程序。Erlang不会在不读取套接字的情况下向套接字"窥视"功能

在二郎中,如何有效地做到这一点?

我提出了一些想法,但似乎都不令人满意:

  • 一个小型的C前端服务器,它探查协议并将其分派到Erlang中的一个端点。缺点:部署复杂
  • 在NIF中暴露MSG_PEEK。缺点:recvmsg可能会阻塞,这会对调度程序造成严重破坏
  • 从套接字读取,然后在自定义的类似套接字的模块中回放完整数据(使用SSL套接字的cb_info选项)。缺点:使用纯Erlang来回代理数据会使实现复杂且速度减慢

需要考虑的是,首先通过gen_tcp:recv/2,3读取几个字节,检查数据以确定要处理的协议,然后使用未记录的gen_tcp:unrecv/2函数将接收到的数据推回套接字。类似这样的东西:

{ok, Data} = gen_tcp:recv(Socket, NumberOfBytesToRead),
ProtocolHandler = decide_which_protocol(Data),
gen_tcp:unrecv(Socket, Data),
ProtocolHandler:handle_this_socket(Socket).

其中decide_which_protocol/1handle_this_socket/1函数代表您自己的逻辑,用于检测和处理两个协议,ProtocolHandler代表用于处理不同协议的不同模块。为此,请确保套接字处于{active,false}模式。如果代码检测到更新的基于TLS的协议,则可以按照此处所述将TCP套接字升级为TLS(搜索"升级示例")。

相关内容

最新更新