Erlang:识别协议而不消耗套接字中的数据

时间:2014-11-01 11:10:15

标签: erlang

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

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

现有的C实现使用recvmsg(MSG_PEEK)从连接开头嗅探几个字节,然后将套接字传递给其中一个处理程序。 Erlang没有公开功能以“偷看”到套接字而不从中读取。

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

我想出了一些想法,但没有一个看起来令人满意:

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

1 个答案:

答案 0 :(得分:6)

需要考虑的是首先通过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")

相关问题