次のコードは{packet,0}
、関数呼び出しのオプションでは機能しgen_tcp:connect()
ますが、1、2、および4では機能しません(ただし、4でのみテストし、1と2も機能しないと想定しています)。私が持っている質問は、なぜそうではないのか、そして一方を他方の上に使用することが重要なのかということです。基本的に、Erlangのドキュメントはパケットオプションに関する主題の詳細な説明を扱っておらず、JoeArmstrongによるProgrammingErlangも詳細を提供していません。彼は、UDPとは異なり、tcpパケットは送信時に受信されると常に思っていましたが、パケットは順番に再構成されないと説明しています。私が持っている興味深いメモの1つは、このページのクライアントサーバーにオプションがあり{packet,4}
、正常に動作し、以下のこのコードと非常によく似ていることです。これがサーバーシェルの出力です{packet,4}
以下のコードで使用されるオプション。
Erlang R16A (erts-5.10) [smp:8:8] [async-threads:10]
Eshell V5.10 (abort with ^G)
1> cd("c:/erlang").
c:/erlang
ok
2> c(cp3).
{ok,cp3}
3> cp3:server().
Started Server:
<0.41.0>
Accept Server:
Pid <0.43.0>
Connection accepted
Accept Server:
Loop Server:
Error on socket #Port<0.2256> reason: einval
これはクライアント側のシェル出力です。
Erlang R16A (erts-5.10) [smp:8:8] [async-threads:10]
Eshell V5.10 (abort with ^G)
1> cd("c:/erlang").
c:/erlang
ok
2> cp3:client().
exit
3>
これは使用されるコードです、
-module(cp3).
-export([client/0, server/0,start/0,accept/1,enter_loop/1,loop/1]).
client() ->
{ok, Socket} = gen_tcp:connect("localhost", 4001,[binary, {packet, 4}]),
ok = gen_tcp:send(Socket, "packet"),
receive
{tcp,Socket,String} ->
io:format("Client received = ~p~n",[String]),
io:format("Client result = ~p~n",[String]),
gen_tcp:close(Socket)
after 1000 ->
exit
end.
server() ->
Pid = spawn(fun()-> start() end),
Pid.
start() ->
io:format("Started Server:~n"),
{ok, Socket} = gen_tcp:listen(4001, [binary, {packet, 4},{reuseaddr, true},{active, false}]),
accept(Socket).
accept(ListenSocket) ->
io:format("Accept Server:~n"),
case gen_tcp:accept(ListenSocket) of
{ok, Socket} ->
Pid = spawn(fun() ->
io:format("Connection accepted ~n", []),
enter_loop(Socket)
end),
io:format("Pid ~p~n",[Pid]),
gen_tcp:controlling_process(Socket, Pid),
Pid ! ack,
accept(ListenSocket);
Error ->
exit(Error)
end.
enter_loop(Socket) ->
%% make sure to acknowledge owner rights transmission finished
receive ack -> ok end,
loop(Socket).
loop(Socket) ->
io:format("Loop Server:~n"),
case gen_tcp:recv(Socket, 6) of
{ok, Data} ->
case Data of
<<"packet">> ->
io:format("Server replying = ~p~n",[Data]),
gen_tcp:send(Socket, Data),
loop(Socket)
end;
{error, Reason} ->
io:format("Error on socket ~p reason: ~p~n", [Socket, Reason])
end.