listen
listen

Reputation: 247

rate of acceptance of sockets when using gen_tcp

I found an interesting problem when using gen_tcp behavior. I have a server and a client. The server accepts connections and the client creates many processes that all try to connect to the listening server.

If I try to start the client which spawns many processes that all try to connect to the socket at the same time then many fail. However if I put timer:sleep(x) then every socket is being accepted.

Does this mean that gen_tcp:accept() has a limit where it can accept some connection request?

Code for the server and the client follows:

 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.

Client:

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.

Upvotes: 0

Views: 342

Answers (1)

Nathaniel Waisbrot
Nathaniel Waisbrot

Reputation: 24473

It is true that a single process can only gen_tcp:accept/1 so fast, though I'm not sure that that's the bottleneck you're running in to.

You might be interested in Ranch, the TCP library for the Cowboy webserver. The manual includes a section on internal features that talks about using multiple acceptors.

In your case, you should try to produce more debugging output for yourself. Printing the error when the client fails to connect would be a good start -- there are lots reasons why a TCP client might fail to connect.

Upvotes: 1

Related Questions