0

というわけで、書いた Python プログラムを Erlang に変換していて、Erlang を使うのは久しぶりです。だから私は初心者レベルに戻ります。とにかく経験から、ソケットを扱うときに使用するすべての言語には、送受信されるデータの長さを常に返す send/recv 関数があります。ただし、Erlangs gen_tcp の場合はそうではないようです。

send/recv/or inet:setopts を呼び出すと、パケットがいつ終了したかがわかりますか? 受信したいパケット (文字列) でエスケープまたは \n を見つけることができるように、ループする recvAll/sendAll 関数を記述する必要がありますか?

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 は知っているように見えます。クライアントは私が書いているPHPソケットライブラリであるため、受信されるデータの長さは20バイトから9216バイトまでの範囲であり、チャンクで送信される可能性があるため、確認したいと思います。

ありがとうございました、

アジム。

4

1 に答える 1

0

TL;DR

send/recv/or inet:setopts を呼び出すと、パケットがいつ終了したかがわかりますか?

いいえ、そうではありません。

受信したいパケット (文字列) でエスケープまたは \n を見つけることができるように、ループする recvAll/sendAll 関数を記述する必要がありますか?

はい、通常はそうします。しかし、erlang がこの仕事をしてくれます。

どうやって?

実際、メッセージをパケットに分割するという意味で TCP に依存することはできませんでした。一般に、TCP はストリームを任意のサイズのチャンクに分割し、プログラムでこのチャンクを組み立てて、このストリームを独自に解析する必要があります。したがって、最初に、プロトコルは「自己区切り」でなければなりません。たとえば、次のことができます。

  1. バイナリ プロトコルでは、各パケットの前にその長さ (固定サイズ フィールド) を付けます。したがって、プロトコル フレームは次のようになります。<<PacketLength:2/big-unsigned-integer, Packet/binary>>
  2. テキスト プロトコルの場合 - 各行を改行記号で終了します。

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 は入力ストリームを内部で解析し、行ごとに分割されたパケットを生成します。

于 2015-03-03T10:26:56.293 に答える