2015-09-18 128 views
2

我正在Erlang編寫一個服務器,並且想要打開大量的連接。問題是我在16358 gen_tcp:connect/3調用後收到{error,eaddrnotavail}。正如你在下面看到的,服務器非常簡單。Erlang gen_server eaddrnotavail在16358之後gen_tcp:連接調用

我修改了我的MacOS約塞米蒂限制; ulimit -n輸出爲6553600.

我開始:

erl +Q 134217727 +P 1000000 -env ERL_MAX_PORTS 40960000 -env ERTS_MAX_PORTS 40960000 

服務器:

-module(naive_server). 
-author("Stefan Stan"). 

-compile(export_all). 

start_server(Port) -> 
    Pid = spawn_link(fun() -> 
    {ok, Listen} = gen_tcp:listen(Port, [binary, {backlog, 6553600}]), 
    spawn(fun() -> acceptor(Listen, 0) end), 
    timer:sleep(infinity) 
    end), 
    {ok, Pid}. 

acceptor(ListenSocket, Nr) -> 
    {ok, Socket} = gen_tcp:accept(ListenSocket), 
    io:format("Client nr ~p connected~n", [Nr]), 
    spawn(fun() -> acceptor(ListenSocket,Nr+1) end), 
    handle(Socket). 

handle(Socket) -> 
    receive 
    {tcp, Socket, <<"quit", _/binary>>} -> 
     gen_tcp:close(Socket); 
    {tcp, Socket, Msg} -> 
     gen_tcp:send(Socket, Msg), 
     handle(Socket) 
    end. 

客戶端:

-module(naive_client). 
-author("Stefan Stan"). 

%% API 
-export([connect_clients/3, connect/1]). 

connect(Port) -> 
    gen_tcp:connect({127,0,0,1}, Port, []). 

connect_clients(Number, Port, List) when is_number(Number), Number >= 0, is_number(Port), Port>0 -> 
    F = 
    fun() -> 
     case Number of 
     0 -> {ok, lists:reverse(List)}; 
     _ -> 
      {ok, Pid} = connect(Port), 
      NewList = [Pid|List], 
      connect_clients(Number-1, Port, NewList) 
     end 
    end, 
    spawn(F). 

回答

2

我想,你可能已經用完了短暫的傳出端口(由您的客戶端使用)。你可以運行:

macosx$ sysctl net.inet.ip.portrange.first net.inet.ip.portrange.last

在我的機器它給了我:

net.inet.ip.portrange.first: 49152 
net.inet.ip.portrange.last: 65535 

不同的是16383,這是非常接近你的電話號碼。

+0

是的,就是這樣。現在我將第一個設置爲1025,最後設置爲65535,我可以打開64510個連接。我現在正在尋找一種更加開放的方式,如果您知道某種方式,請告訴我......感謝您的時間 –

+0

這裏的限制實際上是TCP協議。當你查看tcp頭時,你會看到端口號是16位整數,所以你不能在每個IP上產生超過65535個端口,但是當然你可以添加另一個網絡接口一個不同的IP。我不知道如何在OSX上添加另一個接口/子接口。有時添加另一臺機器會更容易。如果你設法添加一個額外的接口,你可以使用{ip,ip_address()}選項指定在'gen_tcp:connect'選項中使用哪一個接口。 –

+0

確實;我將我的開發人員移動到了Oracle Linux 7上,即使我有參數,我也可以打開超過100K的連接:net.inet.ip.portrange.first:49152 net.inet.ip.portrange.last:65535 OSX很奇怪> 。>無論如何,謝謝你的時間 –