我正在使用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中发送和构建的包,我不熟悉它,包含许多不同类型的数据,而不仅仅是字符串。
答案 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)