tcp - 如何处理 Erlang 中 TCP 流中数据包的错误长度 header ?

标签 tcp erlang gen-tcp

我正在使用 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/

相关文章:

Erlang OTP 主管 gen_tcp - {error,eaddrinuse}

java - BufferedReader.readLine() 阻塞一段时间

linux - SCTP - 协议(protocol)不可达错误

unit-testing - 对并发的Erlang代码进行单元测试的最佳方法是什么?

web-services - gen_tcp获得极高的CPU

sockets - Erlang同时连接1M客户端

delphi tserversocket 忽略第一条消息

file - 通过 TCP 连接传输 mp3 文件。使用 JProgressBar 显示下载进度

java - erlang 可以处理多少并发 http 请求

erlang - 如何为使用 rebar 运行测试的 common_test 指定配置文件