Erlang get_tcp:recv数据长度

0xA*_*xAX 3 sockets erlang

gen_tcp:recv(Socket, 0).是数据接收的用户,但我一次只能接收1418个字节.如何收到已发送的数据量?

I G*_*ERS 7

gen_tcp:recv(Socket, 0)你问内核:"给我现在在接收缓冲区中可用的所有数据".然而,内核也可以免费给你.即使对于相当快速的链接,您可能会在TCP连接上启动慢启动,因此在开始时您将无法获得太多数据.

解决方案是做自己的缓冲.您必须从底层套接字中获取数据,直到您有足够的数据来构造消息.由于这个原因,二进制协议在流之上实现它们自己的消息传递是很常见的.


对于长期记录:常见的消息格式是将消息编码为:

decode(Bin) when is_binary(Bin) ->
  <<Len:32/integer, R/binary>> = Bin,
  <<Payload:Len/binary, Remain/binary>>,
  {msg, {Len, Payload}, Remaining}.
Run Code Online (Sandbox Code Playgroud)

也就是说,消息是4个字节,表示32位bigendian整数,后跟有效负载,其中长度由整数给出.这种格式和其他类似的格式非常常见Erlang包含直接在C层中的优化解析器.要获得对这些内容的访问权限,请在套接字上设置选项inet/setops/2,在我们设置的情况下{packet, 4}.然后我们可以通过设置{active, once}套接字并等待下一条消息来获取消息.当它到达时,我们可以{active, once}再次在套接字上获取下一条消息,依此类推.文档中有一个例子gen_tcp(erl -man gen_tcp如果您正确安装了Erlang手册页).

其他常见格式是asn.1甚至是http标头(!).

技巧

创建一个独立的过程通常是有益的,该过程可以编码和解码您的消息格式,然后将数据发送到系统的其余部分.通常Erlang中的一个很好的解决方案是尽可能快地对传入的数据进行解复用,并将数据传递给进程,然后该进程可以处理剩下的问题.

  • 我倾向于同意.另请注意,SCTP可能是用于消息的正确协议,但遗憾的是没有人关心它:/ (3认同)
  • 很好的答案,为什么这些问题不断出现的问题是TCP被误解为基于消息的协议.如果将其视为可靠的串行线,则会更加清晰. (2认同)