2016-04-08 28 views
0

當使用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. 
+3

您可以在客戶端中打印_Else結果以獲取無法連接到服務器的原因。我已經重新格式化了您的帖子,以便更輕鬆地閱讀它。 看來,當客戶端成功連接時,客戶端不會循環,並且進程立即終止,關閉套接字。 – Pascal

+2

您需要檢查您的TCP偵聽積壓,默認值爲5.您可以通過'{backlog,B}'選項在您的監聽調用中進行設置,其中'B'是一個整數。哦,而且'gen_tcp'不是行爲,它只是一個模塊。 –

回答

1

這是事實,單個進程只能gen_tcp:accept/1這麼快,雖然我不知道,這是您正在運行的瓶頸。

您可能感興趣的Ranch,牛仔網絡服務器的TCP庫。該手冊包含一個討論使用多個接受器的section on internal features

在你的情況下,你應該嘗試爲自己生成更多的調試輸出。當客戶端無法連接時打印錯誤將是一個好的開始 - TCP客戶端可能無法連接的原因很多。