使用gen_tcp

时间:2016-04-08 18:14:19

标签: sockets tcp erlang otp gen-tcp

使用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.

1 个答案:

答案 0 :(得分:1)

确实,单个流程只能gen_tcp:accept/1这么快,但我不确定这是您遇到的瓶颈。

您可能对Ranch,Cowboy网络服务器的TCP库感兴趣。该手册包含section on internal features,其中涉及使用多个接受器。

在您的情况下,您应该尝试为自己生成更多的调试输出。在客户端无法连接时打印错误将是一个良好的开端 - 有很多原因导致TCP客户端无法连接。