【发布时间】:2021-12-05 00:14:25
【问题描述】:
我有一个非常简单的问题,我想创建 20 个子进程,每个子进程都有相同的监听套接字,有 2 种方法我只想知道两者之间有什么区别:
module(sup).
.....
start() ->
supervisor:start_link({local,?MODULE},?MODULE,[]).
%%%%%%%%%%%%%%%%%%
-------第一种方法------
init([]) ->
Listen=gen_tcp:listen(....),
spawn(fun() ->start_children(20) end),
{ok,{{simple_one_for_one,5,1},[{child,{ChildModule,start,[Listen]},....}]}}.
%%%%%%%%%%%%%%%%%
start_children(N) ->
[supervisor:start_child(?MODULE, [])||_ <-lists:seq[1,N]],
ok.
这是一个 simple_one_for_one 树,我只是创建一个监听套接字并将其设置为每个启动的进程的参数,这些进程将在稍后处理它,我产生了一个新进程来运行 start_children/1,因为这个函数调用主管,稍后再调用在它的init/1function 中,它不能在它自己的启动之前启动子进程,所以进程将等待 sup 的启动来调用它,让我们看看第二种方法:
---------第二种方法---------
init([]) ->
ChildSpecs=[{Id,{ChildModule,start,[fun createListenSocket/0]},....}||Id <-lists:seq[1,20]]
{ok,{{one_for_one,5,1},ChildSpecs}}.
%%%%%%%%%%%%%%%%%%%%
createListenSocket() ->
gen_tcp:listen(....).
这是一个 one_for_one 树,sup 在开始时创建了 20 个子节点,有 20 个套接字:每个子节点一个套接字,所以问题是:这两种方法是相同的还是不同的?如果我们认为它们是相同的,则意味着侦听套接字只是一个变量,并且套接字中的特殊事物(侦听传入连接)在我们运行 gen_tcp:accept/1 时开始。
因为如果不是,我们会遇到第一种方法中 20 个进程共享同一个侦听套接字的情况。
编辑:
好吧,我认为 José 已经回答了我的问题,但他的回答给了我另一个问题:如何在 Erlang 中创建多个具有相同端口和 IP 地址的套接字?因为如果我想为每个节点运行 20 个套接字,则 ip 是本地 IP 地址,并且所有套接字都相同,并且在我只需要一个指定端口用于应用程序的情况下,端口也相同?有一个选项{reuseaddr, true} 作为gen_tcp:listen 的参数,但它可以在我们为不同的IP 地址使用相同的端口并且Erlang 中没有reuseport 时使用,那该怎么办?
【问题讨论】:
标签: sockets tcp erlang elixir erlang-otp