接收未知的字符串长度?

时间:2015-02-25 17:47:48

标签: sockets erlang gen-tcp

所以我正在将我编写的Python程序转换为Erlang,自从我使用Erlang以来已经有很长一段时间了。所以我邀请我回到初级水平。无论如何,在处理套接字时我使用的每种语言都有send / recv函数,它们总是返回发送/接收数据的长度。但在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。

1 个答案:

答案 0 :(得分:0)

TL; DR

  

所以当我调用send / recv /或inet:setopts时,它知道数据包的时间   结束?

不,它没有。

  

我是否需要编写一个循环的recvAll / sendAll函数,以便找到   我希望收到的数据包(字符串)中的转义符\ n是什么?

是的,一般来说,你会的。但是erlang可以为你完成这项工作。

怎么样?

实际上,在将消息拆分为数据包时,您无法依赖TCP。通常,TCP会将您的流拆分为任意大小的块,并且程序必须组装此块并通过自己解析此流。所以,首先,你的协议必须是“自我划分”。例如,您可以:

  1. 在二进制协议中 - 在每个数据包之前加上其长度(固定大小字段)。因此,协议框架将如下所示:<<PacketLength:2/big-unsigned-integer, Packet/binary>>
  2. 在文本协议中 - 使用换行符号终止每一行。
  3. 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将在内部解析输入流,并按行拆分数据包。