【问题标题】:Why no need to remember the socket handle in handle_info?为什么不需要记住handle_info中的套接字句柄?
【发布时间】:2015-09-19 11:13:22
【问题描述】:

我对第 4 章的“Erlang and OTP in action”示例感到困惑。 https://github.com/erlware/Erlang-and-OTP-in-Action-Source/blob/master/chapter_04/tcp_rpc/src/tr_server.erl#L92

handle_info(timeout, #state{lsock = LSock} = State) ->
    {ok, _Sock} = gen_tcp:accept(LSock),
    {noreply, State}.

书上说:

你不需要记住accept返回的socket句柄, 因为它也包含在每个数据包中。

具体是什么意思?什么是“数据包”? 为什么套接字句柄名称带有下划线前缀?为什么不需要在 GC 的情况下将其保存在某个地方?幕后发生了什么?

gen_server 的行为似乎很难遵循。有人可以简单明了地解释一下吗?

【问题讨论】:

  • 我前段时间写了一个答案,解释了basics of OTP behaviours,也许它可以帮助您更好地了解gen_server

标签: erlang


【解决方案1】:

当你在 erlang 中与 tcp 套接字建立连接时,你可以使套接字处于活动或不活动状态。

如果套接字处于活动状态,每次您从客户端接收到一些数据时,它都会作为 Erlang 消息发送,格式为 {tcp, Socket, Data}tcp 只是元组 id,Socket 是一个变量,您可以在其中有关于 Socket 的所有信息,比如你在哪个本地端口上监听,在哪个接口上,以及发送数据的对端的端口/IP,Data 是发送的数据。

这就是你不需要记住 Socket 的原因,因为每次你收到一个包裹时,你都会有Socket作为消息的参数。

如果您将套接字设置为非活动,则需要使用函数recv/2 才能接收任何数据。活动套接字更容易使用,但是如果您的流量过多,它可能会使 Erlang 消息传递系统过载,因此当您期望高负载时,您总是使用非活动套接字。

“数据包”基本上是通过连接发送的一个包,在这个例子中,客户端发送的命令只是在一个数据包中发送,因为它是一个小包,但想象一下客户端必须发送的数据发送给你,而不是 10 或 20 个字符,就像 100kb,你不会在一个包中得到它,你会在不同的包中得到数据,作为程序员,你有责任把你得到的所有数据将多个数据包放在一起。

在 Erlang 中,当你进行模式匹配时,你可以匹配任何带有下划线的东西,比如

{expected, _} = {expected, Anything}

无论你在变量 Anything 上绑定了什么,模式匹配总是正确的。现在,假设您在代码中都有下划线,有时它会感到困惑并且您想添加更好的代码文档,因此您在下划线之后添加一些东西,例如

{expected, _MiddleName} = {expected, Anything}

所以现在您不需要关心中间名,因为您根本不需要它,但是您在代码中记录了元组的第二个值应该具有中间名的内容。

垃圾收集器不会收集正在使用的 Socket。

gen_server 只是一个用 Erlang 编写的通用服务器,它实际上是一个很大的话题,因为它是 OTP 架构的一部分,你可以在这个 link 上找到一个很好的教程,但总之,当你开始使用 erlang ,您意识到您编写了相同的代码来初始化服务器(我不是在谈论 tcp 服务器,而是关于 Erlang 服务器,这是一个侦听 Erlang 消息并在收到任何消息时采取行动和回答的进程,或者不,它将回答同步消息,不会回答异步消息)。所以正如我所说,随着时间的推移,你会意识到你一遍又一遍地编写相同的初始化、相同的 init 函数等。

otp_server 只是一个 Erlang 模块,它抽象了您使用的相同代码,一遍又一遍地重复,并让您只需专注于编写执行某些自定义功能的真实代码的任务,以便为其客户提供服务,并且因为它被每个人使用,它提供了一个固定的结构,每个 erlang 程序员都可以理解,并且每个程序员都可以遵循而不会出现重大问题。在我给你的链接上,它展示了一个完美的例子,在没有 otp 的情况下编写 Erlang 服务器模块,为你的所有下一个服务器模块编写通用服务器模块模板,最后解释了它正是 OTP 为你做的。

【讨论】:

  • 非常感谢!它详细而有用。链接是手册页吗?例子在哪里?
  • 我也很感谢您投赞成票 :) 欢迎来到 Erlang 世界,一旦你完成了 Erlang 的学习,别忘了检查一下 elixir。
猜你喜欢
  • 2018-05-30
  • 2013-05-19
  • 1970-01-01
  • 1970-01-01
  • 2021-01-19
  • 2021-12-05
  • 1970-01-01
  • 1970-01-01
  • 2022-01-25
相关资源
最近更新 更多