我需要在Erlang中的单个侦听套接字上处理两个不兼容的协议版本.
遗憾的是,协议升级设计不正确,因此在较旧的协议中切换到较新的协议或版本控制中的"升级协议"选项,新协议是普通的TLS连接(较旧的是普通的TCP请求 - 响应行导向的) ).
现有的C实现用于recvmsg(MSG_PEEK)
从连接开始嗅探几个字节,然后将套接字传递给其中一个处理程序.Erlang没有公开功能以"偷看"到套接字而不从中读取.
如何在Erlang中有效地做到这一点?
我想出了一些想法,但没有一个看起来令人满意:
一个小型的C前端服务器,它嗅探协议并调度到Erlang中的一个端点.缺点:使部署复杂化.
暴露MSG_PEEK
于NIF.缺点:recvmsg可能会阻塞,这会对调度程序造成严重破坏.
从套接字读取,然后在自定义套接字模块中重放完整数据(使用cb_info
SSL套接字选项).缺点:使用纯Erlang来回代理数据会使实现变得复杂并减慢速度.
Steve Vinosk.. 6
要考虑的是首先通过读取几个字节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/1
和handle_this_socket/1
函数代表您自己的逻辑,用于检测和处理两个协议,并ProtocolHandler
代表处理不同协议的不同模块.确保套接字处于{active,false}
此模式.如果代码检测到较新的基于TLS的协议,则可以按照此处的说明将TCP套接字升级到TLS (搜索"升级示例").
要考虑的是首先通过读取几个字节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/1
和handle_this_socket/1
函数代表您自己的逻辑,用于检测和处理两个协议,并ProtocolHandler
代表处理不同协议的不同模块.确保套接字处于{active,false}
此模式.如果代码检测到较新的基于TLS的协议,则可以按照此处的说明将TCP套接字升级到TLS (搜索"升级示例").