收到未知的字符串长度?
Receiving unknown strings lengths?
所以我正在将我写的一个Python程序转换成Erlang,我已经很久没有使用Erlang了。所以我猜我又回到了初学者水平。无论如何,根据经验,我在处理套接字时使用的每种语言都有 send/recv 函数,这些函数总是 return 数据长度 sent/receive。然而,在 Erlangs gen_tcp 案例中似乎并没有这样做。
所以当我调用send/recv/或inet:setopts时它知道数据包何时结束?我是否需要编写循环 recvAll/sendAll 函数以便在我希望接收的数据包(字符串)中找到转义符或 \n?
http://erlang.org/doc/man/gen_tcp.html#recv-2
我正在使用的示例代码:
server(LS) ->
case gen_tcp:accept(LS) of
{ok,S} ->
loop(S),
server(LS);
Other ->
io:format("accept returned ~w - goodbye!~n",[Other]),
ok
end.
loop(S) ->
inet:setopts(S,[{active,once}]),
receive
{tcp,S,Data} ->
Answer = process(Data), % Not implemented in this example
gen_tcp:send(S,Answer),
loop(S);
{tcp_closed,S} ->
io:format("Socket ~w closed [~w]~n",[S,self()]),
ok
end.
仅通过查看示例和文档,Erlang 似乎就知道了。我想确认一下,因为接收到的数据长度可以在 20 字节到 9216 字节之间的任何地方,或者可以分块发送,因为客户端是我正在编写的 PHP 套接字库。
谢谢,
Ajm.
TL;DR
So when I call send/recv/or inet:setopts it knows when the packet has
ended?
不,不是。
Will I need to write a looping recvAll/sendAll function so I can find
the escape or \n in the packet(string) I wish to receive?
是的,通常你会。但是 erlang 可以为您完成这项工作。
怎么做?
实际上,在将消息拆分为数据包的意义上,您不能依赖 TCP。通常,TCP 会将您的流拆分为任意大小的块,并且您的程序必须 assemble 这个块并自己解析这个流。因此,首先,您的协议必须是 "self delimiting"。例如你可以:
- 在二进制协议中——在每个数据包之前加上它的长度(固定大小的字段)。因此,协议框架将如下所示:
<<PacketLength:2/big-unsigned-integer, Packet/binary>>
- 在文本协议中 - 每行以换行符结束。
Erlang 可以帮助您完成这笔交易。看看这里 http://erlang.org/doc/man/gen_tcp.html#type-option。有重要选项:
{packet, PacketType}(TCP/IP sockets)
Defines the type of packets to use for a socket. The following values are valid:
raw | 0
No packaging is done.
1 | 2 | 4
Packets consist of a header specifying the number of bytes in the packet, followed by that number of bytes. The length of header can be one, two, or four bytes; containing an unsigned integer in big-endian byte order. Each send operation will generate the header, and the header will be stripped off on each receive operation.
In current implementation the 4-byte header is limited to 2Gb.
line
Line mode, a packet is a line terminated with newline, lines longer than the receive buffer are truncated.
最后一个选项 (line
) 对您来说最有趣。如果您设置此选项,erlang 将在内部解析输入流并生成按行拆分的数据包。
所以我正在将我写的一个Python程序转换成Erlang,我已经很久没有使用Erlang了。所以我猜我又回到了初学者水平。无论如何,根据经验,我在处理套接字时使用的每种语言都有 send/recv 函数,这些函数总是 return 数据长度 sent/receive。然而,在 Erlangs gen_tcp 案例中似乎并没有这样做。
所以当我调用send/recv/或inet:setopts时它知道数据包何时结束?我是否需要编写循环 recvAll/sendAll 函数以便在我希望接收的数据包(字符串)中找到转义符或 \n?
http://erlang.org/doc/man/gen_tcp.html#recv-2
我正在使用的示例代码:
server(LS) ->
case gen_tcp:accept(LS) of
{ok,S} ->
loop(S),
server(LS);
Other ->
io:format("accept returned ~w - goodbye!~n",[Other]),
ok
end.
loop(S) ->
inet:setopts(S,[{active,once}]),
receive
{tcp,S,Data} ->
Answer = process(Data), % Not implemented in this example
gen_tcp:send(S,Answer),
loop(S);
{tcp_closed,S} ->
io:format("Socket ~w closed [~w]~n",[S,self()]),
ok
end.
仅通过查看示例和文档,Erlang 似乎就知道了。我想确认一下,因为接收到的数据长度可以在 20 字节到 9216 字节之间的任何地方,或者可以分块发送,因为客户端是我正在编写的 PHP 套接字库。
谢谢,
Ajm.
TL;DR
So when I call send/recv/or inet:setopts it knows when the packet has ended?
不,不是。
Will I need to write a looping recvAll/sendAll function so I can find the escape or \n in the packet(string) I wish to receive?
是的,通常你会。但是 erlang 可以为您完成这项工作。
怎么做?
实际上,在将消息拆分为数据包的意义上,您不能依赖 TCP。通常,TCP 会将您的流拆分为任意大小的块,并且您的程序必须 assemble 这个块并自己解析这个流。因此,首先,您的协议必须是 "self delimiting"。例如你可以:
- 在二进制协议中——在每个数据包之前加上它的长度(固定大小的字段)。因此,协议框架将如下所示:
<<PacketLength:2/big-unsigned-integer, Packet/binary>>
- 在文本协议中 - 每行以换行符结束。
Erlang 可以帮助您完成这笔交易。看看这里 http://erlang.org/doc/man/gen_tcp.html#type-option。有重要选项:
{packet, PacketType}(TCP/IP sockets)
Defines the type of packets to use for a socket. The following values are valid:
raw | 0
No packaging is done.
1 | 2 | 4
Packets consist of a header specifying the number of bytes in the packet, followed by that number of bytes. The length of header can be one, two, or four bytes; containing an unsigned integer in big-endian byte order. Each send operation will generate the header, and the header will be stripped off on each receive operation.
In current implementation the 4-byte header is limited to 2Gb.
line
Line mode, a packet is a line terminated with newline, lines longer than the receive buffer are truncated.
最后一个选项 (line
) 对您来说最有趣。如果您设置此选项,erlang 将在内部解析输入流并生成按行拆分的数据包。