如何处理Erlang中TCP流中数据包的错误长度标头?

时间:2014-04-21 16:35:44

标签: tcp erlang gen-tcp

我正在使用gen_tcp在Erlang上通过TCP接收消息。通过使用{packet, 4}选项指定的4字节长度的报头将流分成数据包。我打电话给gen_tcp:listen/2

gen_tcp:listen(Port, [binary, inet, {active, once}, {packet, 4}]).

正如您所看到的,我使用了{active, once}选项,因此我可以从进程邮箱中获取数据包,而不会充斥它。只要长度标题正确,这就可以正常工作。如果不是,任何事情都可能发生。所以我想以某种方式处理错误数据包的可能性。

这有点棘手,因为我实际上在处理流。忽略错误的数据包是可以的,但是如何让Erlang跳过这些数据包并识别后续数据包?这个问题通常是如何处理的?

使用分隔符更好吗?我查看了packet的其他gen_tcp个选项。特别是以下内容:

asn1 | cdr | sunrm | fcgi | tpkt | line

唯一真正理解其含义的是line,但我认为这不是一个好选择。我期待收到在Objective C中发送和构建的包,我不熟悉它,包含许多不同类型的数据,而不仅仅是字符串。

1 个答案:

答案 0 :(得分:4)

我不认为你可以跳过"坏"使用{packet,N}时的数据包

主要原因是,什么是坏包?

任何4个字节都可以表示大小,所以如果有人发送了: 你好\ n

你真的得到了: 0x48656c6c 作为大小标题,表示帧为:1214606444字节长 其次是" o \ n" 然后你就挂了

您可以设置{packet_size,1024}(或其他)以防止您分配1.2gb"您好"

不确定是否会返回错误或丢弃套接字。

由于邮件在传输过程中被任意分割,因此无法从TCP中的错误框架中恢复。

如果你不使用{packet,N},那么你必须自己进行分段控制,比如你得到文本行,你需要知道消息何时结束。

如果您控制客户端/服务器协议,您可能希望使用{packet,http}或更完整的我们解决方案,例如cowboy

然后你让客户提交http请求(正文仍然可以通过二进制),而framwork会处理格式错误的请求。

如果你需要双向通道,websockets可能仍然可以(假设你在目标c中有一个websocket lib)