【问题标题】:Erlang: discerning protocol without consuming data from a socketErlang:识别协议而不消耗来自套接字的数据
【发布时间】:2014-12-28 14:27:34
【问题描述】:

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

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

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

如何在 Erlang 中高效地做到这一点?

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

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

【问题讨论】:

  • 我不明白你的解释是什么阻止你模仿 C 实现,模式匹配通常非常适合这项工作。
  • 从您的问题中不清楚旧协议是仅 TCP 而新协议是 TLS,还是它们都是 TLS? C 代码是否只是在进行常规监听/接受,然后在嗅探后升级到 TLS?
  • @Pascal Erlang 没有提供任何方法来“窥视”流而不读取它。
  • @SteveVinoski 旧版本是纯 TCP 请求响应版本。我已经更新了问题。
  • @SteveVinoski 是的,旧代码会监听/接受,recvmsg(MSG_PEEK) 并启动旧的请求-响应协议或 TLS 会话。

标签: erlang


【解决方案1】:

需要考虑的是首先通过gen_tcp:recv/2,3 读取几个字节,检查数据以确定您正在处理的协议,然后使用undocumented gen_tcp:unrecv/2 function 将接收到的数据推回套接字。像这样的:

{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 为 described here (search for "Upgrade example")

【讨论】:

  • unrecv 正是我们所需要的。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-02
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-04
相关资源
最近更新 更多