Erlang gen_tcp:listen/2 用于 IPv6

发布于 2024-12-17 16:43:28 字数 1548 浏览 4 评论 0原文

我有 .NET TCP 发送器发送到 Erlang 接收器。 .NET 组件在解析 localhost 时喜欢使用 IPv6 地址 ::1。我不太确定如何让 Erlang 使用 gen_tcp 监听 IPv6 地址。这是我的尝试。我是否告诉错误的套接字进行监听?谢谢!

listen(Config) ->
    PortString = Config#cfg.eventbusport,
    GoodPort = check_int(PortString),
    Port = if GoodPort -> 
               list_to_integer(PortString);
           true ->
               ?DEFAULT_PORT
           end,                      %% IPv6 here --->
    {ok, XSocket} = gen_tcp:listen(Port, [binary, {packet, line}, {active, false}, {reuseaddr, true}, inet6, {ip, {0,0,0,0,0,0,0,1}}])
    end,
    accept(XSocket, Config).

accept(LSocket, Config) ->
    case gen_tcp:accept(LSocket) of
        {ok, Socket} ->
            spawn_link(fun() -> loop(Socket, Config) end),
            accept(LSocket, Config);
        {error, closed} ->
            logger("Accept: Closed socket.",[],1),
            listen(Config)
    end.

loop(Socket, Config) ->
    case inet:setopts(Socket, [{recbuf, 64000}]) of
        ok ->
            case gen_tcp:recv(Socket, 0) of
                {ok, Data} ->
                    SplitData = binary:split(Data,?CRLF,[global]),
                    discrim(SplitData, Config),
                    loop(Socket, Config);
                {error, closed} ->
                    logger("Loop: Closed socket.",[],1),
                    ok
            end;
        {error, Reason} ->
            logger("ERROR: Couldn't set the recbuf to 64k! Because ~p",[Reason],1)
    end.

I have .NET TCP Sender sending to an Erlang receiver. The .NET component likes to use the IPv6 address ::1 when resolving localhost. I'm not quite sure how to get Erlang to listen on the IPv6 address using gen_tcp. Here's my attempt. Am I telling the wrong socket to do the listening? Thanks!

listen(Config) ->
    PortString = Config#cfg.eventbusport,
    GoodPort = check_int(PortString),
    Port = if GoodPort -> 
               list_to_integer(PortString);
           true ->
               ?DEFAULT_PORT
           end,                      %% IPv6 here --->
    {ok, XSocket} = gen_tcp:listen(Port, [binary, {packet, line}, {active, false}, {reuseaddr, true}, inet6, {ip, {0,0,0,0,0,0,0,1}}])
    end,
    accept(XSocket, Config).

accept(LSocket, Config) ->
    case gen_tcp:accept(LSocket) of
        {ok, Socket} ->
            spawn_link(fun() -> loop(Socket, Config) end),
            accept(LSocket, Config);
        {error, closed} ->
            logger("Accept: Closed socket.",[],1),
            listen(Config)
    end.

loop(Socket, Config) ->
    case inet:setopts(Socket, [{recbuf, 64000}]) of
        ok ->
            case gen_tcp:recv(Socket, 0) of
                {ok, Data} ->
                    SplitData = binary:split(Data,?CRLF,[global]),
                    discrim(SplitData, Config),
                    loop(Socket, Config);
                {error, closed} ->
                    logger("Loop: Closed socket.",[],1),
                    ok
            end;
        {error, Reason} ->
            logger("ERROR: Couldn't set the recbuf to 64k! Because ~p",[Reason],1)
    end.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

樱娆 2024-12-24 16:43:28

您遇到的实际问题是什么?

您可能应该将套接字的控制进程设置为您生成的进程以使用连接。因此,在您的 accept/2 中,您将执行以下操作:

accept(LSocket, Config) ->
    case gen_tcp:accept(LSocket) of
        {ok, Socket} ->
            Pid = spawn_link(fun() -> loop(Socket, Config) end),
            gen_tcp:controlling_process(Socket, Pid),
            accept(LSocket, Config);
...

编写接受循环的另一种方法是生成新的接受循环。你会得到类似这样的结果:

accept_loop(LSocket, Config) ->
    {ok,Socket} = gen_tcp:accept(LSocket),
    spawn_link(fun() -> accept_loop(LSocket, Config) end),
    loop(Socket, Config).

这没有错误处理。您可以毫无问题地将侦听套接字传递给其他进程。当然,如果打开侦听套接字的进程死亡,则套接字将被关闭。

What is the actual problem you are having?

You should probably set the controlling process of the socket to the process you spawn to use the connection. So in your accept/2 you would do something like:

accept(LSocket, Config) ->
    case gen_tcp:accept(LSocket) of
        {ok, Socket} ->
            Pid = spawn_link(fun() -> loop(Socket, Config) end),
            gen_tcp:controlling_process(Socket, Pid),
            accept(LSocket, Config);
...

Another way of writing the accept loop is too spawn new accept loops instead. You get something like:

accept_loop(LSocket, Config) ->
    {ok,Socket} = gen_tcp:accept(LSocket),
    spawn_link(fun() -> accept_loop(LSocket, Config) end),
    loop(Socket, Config).

This without the error handling. You can pass the listen socket to other processes without problems. Of course, if the process which opened the listen socket dies then the socket is closed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文