1

我正在使用 Erlang 通过 TCP 接收消息gen_tcp。如选项所指定,使用 4 字节长度的标头将流划分为数据包{packet, 4}。这就是我所说的gen_tcp:listen/2

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

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

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

使用分隔符更好吗?我已经查看packetgen_tcp. 特别是以下内容:

asn1 | cdr | sunrm | fcgi | tpkt | line

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

4

1 回答 1

4

我认为您在使用 {packet,N} 时不能跳过“坏”数据包

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

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

你实际上得到:0x48656c6c 作为大小头,表示帧是:1214606444 字节长,后跟“o\n”,然后你会挂起

您可以设置 {packet_size,1024} (或其他)以防止您在“hello”上分配 1.2gb

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

由于消息在传输过程中被任意拆分,因此实际上无法从 TCP 中的不良帧中恢复。

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

如果您控制客户端/服务器协议,您可能需要使用 {packet,http} 或更成熟的我们解决方案,如牛仔

然后你让客户端提交 http 请求(body 仍然可以是二进制的),框架会为你处理格式错误的请求。

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

于 2014-04-22T01:28:34.357 回答