erlang: to controlling_process(), or not to controlling_proc



考虑以下简单echo服务器的erlang代码:

回声侦听器:

-module(echo_listener).
-export([start_link/1]).
-define(TCP_OPTIONS, [binary, {packet, 0}, {reuseaddr, true},
                        {keepalive, true}, {backlog, 30}, {active, false}]).
start_link(ListenPort) ->
    {ok, ListenSocket} = gen_tcp:listen(ListenPort, ?TCP_OPTIONS),
    accept_loop(ListenSocket).
accept_loop(ListenSocket) ->
    {ok, ClientSocket} = gen_tcp:accept(ListenSocket),
    Pid = spawn(echo_worker, usher, [ClientSocket]),
    gen_tcp:controlling_process(ClientSocket, Pid),
    accept_loop(ListenSocket).

回声工人:

-module(echo_worker).
-export([echo/1]).
echo(ClientSocket) ->
    case gen_tcp:recv(ClientSocket, 0) of
        {ok, Data} ->
            gen_tcp:send(ClientSocket, Data),
            echo(ClientSocket);
        {error, closed} ->
            ok
    end.

当一个客户端套接字被接受时,echo服务器生成一个echo worker并将客户端套接字直接作为函数参数传递。在代码中有controller_process(),但我在没有调用controlling_process()的情况下尝试了代码,它也有效。

controlling_process()的真正目的是什么?什么时候需要?

Erlang文档说关于gen_tcp:controlling_process/1:

给套接字分配一个新的控制进程Pid。控制进程是从套接字接收消息的进程。如果由除当前控制进程之外的任何其他进程调用,{error, not_owner}返回。

你创建了监听套接字选项{active, false},你读取套接字与gen_tcp:recv/2同步,所以你的代码将工作,即使没有调用gen_tcp:controlling_process/1。然而,如果你想异步接收数据,你必须用选项{active, true}创建监听套接字。在这种情况下,接受连接的所有者将收到关于传入数据的消息。因此,如果你不调用gen_tcp:controlling_process/1,这些消息将被发送到监听进程,而不是工作进程。

最新更新