0

gen_tcpビヘイビアを使用しているときに、興味深い問題が見つかりました。サーバーとクライアントがあります。サーバーは接続を受け入れ、クライアントは多くのプロセスを作成し、それらすべてがリッスン サーバーに接続しようとします。

すべてが同時にソケットに接続しようとする多くのプロセスを生成するクライアントを起動しようとすると、多くのプロセスが失敗します。ただし、置くtimer:sleep(x)と、すべてのソケットが受け入れられます。

gen_tcp:accept()これは、接続要求を受け入れることができる制限があることを意味しますか?

サーバーとクライアントのコードは次のとおりです。

 accept(State = #state{lsocket = LSocket, num = Num}) ->
   case gen_tcp:accept(LSocket) of
     {ok, Socket} ->
       io:format("Accepted ~p ~n", [Num]),
       {sockets, List} = hd(ets:lookup(csockets, sockets)),
       NewList = [Socket | List],
       ets:insert(csockets, {sockets, NewList}),
       Pid = spawn(fun() -> loop(Socket) end),
       gen_tcp:controlling_process(Socket, Pid),
       accept(State#state{num = Num + 1});
     {error, closed} -> State
   end.

 loop(Socket) ->
   case gen_tcp:recv(Socket, 0) of
     {ok, Data} ->
       gen_tcp:send(Socket, Data),
       loop(Socket);
     {error, closed} ->
       io:format(" CLOSED ~n"),
       ok
   end.

クライアント:

send(State = #state{low = Low, high = Low}) ->
  State;
send(State = #state{low = Low}) ->
  N = Low rem 10,
  Dest = lists:nth(N + 1, State#state.dest),
  spawn(?MODULE, loop, [Dest, Low]),
  %%timer:sleep(1),
  NewState = State#state{low = Low + 1},
  send(NewState).

loop({IP, Port}, Low) ->
  case gen_tcp:connect(IP, Port, [binary]) of
    {ok, Socket} ->
      io:format("~p Connected ~n", [Low]),
      gen_tcp:send(Socket, "Hi"),
      receive
        {tcp, RecPort, Data} ->
          io:format("I have received ~p on port ~p  ~p ~n", [Data, RecPort, Low])
      end;
    _Else ->
      io:format("The connection failed ~n"),
      loop({IP, Port}, Low)
  end.
4

1 に答える 1

1

確かに、1 つのプロセスが非常に高速にしか実行できないのは事実ですが、それがgen_tcp:accept/1あなたが直面しているボトルネックであるかどうかはわかりません。

Cowboy Web サーバーの TCP ライブラリである Ranch に興味があるかもしれません。マニュアルには、複数のアクセプターの使用について説明する内部機能に関するセクションが含まれています。

あなたの場合、自分用にもっと多くのデバッグ出力を生成するようにしてください。クライアントが接続に失敗したときにエラーを出力することは良い出発点です。TCP クライアントが接続に失敗する理由はたくさんあります。

于 2016-04-10T11:43:53.130 に答える