gpt4 book ai didi

sockets - Erlang gen_tcp :recv(Socket, 长度)语义

转载 作者:可可西里 更新时间:2023-11-01 02:47:46 37 4
gpt4 key购买 nike

看完this answer ,我想了解是否同样适用于对 gen_tcp:recv(Socket, Length) 的调用。我对文档的理解是,如果缓冲区中有超过 Length 个字节可用,它们将保留在那里;如果少于 Length 字节,调用将阻塞,直到有足够的可用字节或连接关闭。

特别是,当数据包以 2 个字节为前缀以小端顺序保存数据包长度时,这应该有效:

receive_packet(Socket) ->
{ok, <<Length:16/integer-little>>} = gen_tcp:recv(Socket, 2),
gen_tcp:recv(Socket, Length).

这是正确的吗?

最佳答案

是(或否,详见评论)。

考虑:

外壳 1:

1> {ok, L} = gen_tcp:listen(8080, [binary, {packet, 0}, {active, false}]).
{ok,#Port<0.506>}
2> {ok, C} = gen_tcp:accept(L). %% Blocks
...

外壳 2:

1> {ok, S} = gen_tcp:connect("localhost", 8080, [binary, {packet, 0}]).
{ok,#Port<0.516>}
2> gen_tcp:send(S, <<0,2,72,105>>).
ok
3>

外壳 1 续:

...
{ok,#Port<0.512>}
3> {ok, <<Len:16/integer>>} = gen_tcp:recv(C, 2).
{ok,<<0,2>>}
4> Len.
2
5> {ok, Data} = gen_tcp:recv(C, Len).
{ok,<<"Hi">>}
6>

但是,如果您只想确认行为,这很有用。实际上,您可以更改 {packet, N} 选项来定义数据包长度应该有多少字节(在大端系统上)。

与之前相同,但没有显式提取长度(注意 shell 1 中的数据包长度 = 2):

外壳 1:

1> {ok, L} = gen_tcp:listen(8080, [binary, {packet, 2}, {active, false}]).
{ok,#Port<0.506>}
2> {ok, C} = gen_tcp:accept(L). %% Blocks
...

在这种情况下,Erlang 将去除前 2 个字节,recv/2 将阻塞直到它需要的字节数。在这种情况下,在 recv/2 中读取长度必须为 0。

外壳 2:

1> {ok, S} = gen_tcp:connect("localhost", 8080, [binary, {packet, 0}]).
{ok,#Port<0.516>}
2> gen_tcp:send(S, <<0,2,72,105>>).
ok
3>

外壳 1:

...
{ok,#Port<0.512>}
3> {ok, Data} = gen_tcp:recv(C, 0).
{ok,<<"Hi">>}

在这种情况下,我没有在 shell 2 中指定 {packet, N} 选项只是为了展示这个想法,但通常它不是 0。如果 packet选项设置后 gen_tcp 将自动从包中添加/删除那么多字节。

如果您指定数据包 0,那么您必须执行长度 >= 0 的 recv/2 并且行为与 C 中的相同。您可以通过给出一个 short 来模拟非阻塞接收接收时超时,在这种情况下将返回 {error, timeout}。

更多信息可以在这里阅读: http://www.erlang.org/doc/man/gen_tcp.htmlhttp://www.erlang.org/doc/man/inet.html#setopts-2

希望这能解决问题。

关于sockets - Erlang gen_tcp :recv(Socket, 长度)语义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3778546/

37 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com