【问题标题】:Erlang gen_server eaddrnotavail after 16358 gen_tcp:connect callsErlang gen_server eaddrnotavail 后 16358 gen_tcp:connect 调用
【发布时间】:2015-12-15 05:09:32
【问题描述】:

我正在用 Erlang 写一个服务器,想打开大量的连接。问题是我在 16358 gen_tcp:connect/3 电话后收到 {error, eaddrnotavail}。如下所示,服务器非常简单。

我修改了我的 MacOS Yosemite 限制; 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).

【问题讨论】:

    标签: macos erlang connect gen-server


    【解决方案1】:

    我认为,您可能已经用完了短暂的传出端口(由您的客户端使用)。你能跑吗:

    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,和你的号码很接近。

    【讨论】:

    • 是的,就是这样。现在我将第一个设置为 1025,最后一个设置为 65535,我可以打开 64510 个连接。我现在正在寻找一种打开更多的方法,如果您知道一种方法,请告诉我...感谢您的宝贵时间
    • 这里的限制其实是TCP协议。当您查看 tcp 标头时,您会看到端口号是一个 16 位整数,因此您将无法为每个 IP 生成超过 ~ 65535 个端口,但当然您可以添加另一个网络接口不同的IP。我不知道如何在 OSX 上添加另一个接口/子接口。有时添加另一台机器更容易。如果您设法添加一个额外的接口,您可以使用 {ip, ip_address()} 选项在 gen_tcp:connect 选项中指定要使用的接口。
    • 确实;我在 Oracle Linux 7 上移动了我的开发人员,即使我有参数,我也可以打开超过 100K 的连接:net.inet.ip.portrange.first: 49152 net.inet.ip.portrange.last: 65535 OSX 很奇怪>。 > 无论如何,谢谢你的时间
    猜你喜欢
    • 2011-08-09
    • 2014-11-09
    • 2011-10-08
    • 2016-08-09
    • 2014-05-12
    • 2016-01-13
    • 1970-01-01
    • 2012-09-05
    • 2013-01-22
    相关资源
    最近更新 更多