我正在使用 gen_tcp
在 Erlang 中通过 TCP 接收消息。根据 {packet, 4}
选项的指定,流通过使用 4 字节长度的 header 分成数据包。这就是我调用 gen_tcp:listen/2
的方式:
gen_tcp:listen(Port, [binary, inet, {active, once}, {packet, 4}]).
如您所见,我使用了 {active, once}
选项,这样我就可以从进程邮箱中获取我的数据包,而不会淹没它。只要长度 header 正确,这就可以正常工作。如果不是,任何事情都可能发生。所以我想以某种方式处理错误数据包的可能性。
这有点棘手,因为我实际上是在处理流。忽略错误的数据包是可以的,但是如何让 Erlang 跳过这些数据包并识别后续数据包呢?通常如何处理这个问题?
使用定界符更好吗?我查看了 gen_tcp
的其他一些 packet
选项。特别是以下内容:
asn1 | cdr | sunrm | fcgi | tpkt | line
我真正理解的唯一一个是line
,但我认为这不是一个好的选择。我期待收到用我不熟悉的 Objective C 发送和构建的包,其中包含许多不同类型的数据,而不仅仅是字符串。
最佳答案
我不认为你可以在使用 {packet,N} 时跳过“坏”数据包
主要原因是,什么是坏数据包?
任何 4 个字节都可以表示大小,所以如果有人发送: 你好\n
你实际上得到: 0x48656c6c 作为 size header,表示帧长为:1214606444 bytes 接着是“o\n” 然后你就挂了
您可以设置 {packet_size,1024}(或其他)来避免在“hello”上分配 1.2gb
不确定是否返回错误或丢弃套接字。
实际上没有办法从 TCP 中的错误帧中恢复,因为消息在传输过程中被任意分割。
如果你不使用 {packet,N} 那么你将不得不做你自己的分段控制,假设你得到文本行,你需要知道消息何时结束。
如果您控制客户端/服务器协议(protocol),您可能需要使用 {packet,http} 或更成熟的解决方案,如 cowboy
然后您让客户端提交 http 请求(正文仍然可以是二进制的),框架为您处理格式错误的请求。
如果你需要一个双向 channel ,websockets 可能仍然没问题(假设你在 objective-c 中有一个 websocket 库)
关于tcp - 如何处理 Erlang 中 TCP 流中数据包的错误长度 header ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23201535/