美文网首页
Erlang Socket消息获取模式主动 被动 混合

Erlang Socket消息获取模式主动 被动 混合

作者: 空语 | 来源:发表于2016-04-06 17:31 被阅读0次

    1、主动消息获取(非阻塞)
    第一个例子是以主动模式打开socket,然后接受来自socket的数据:
    {ok,Listen} = gen_tcp:listen(Port,[…,{active,true}…]),
    {ok,Socket} = gen_tcp:accept(Listen), loop(Socket).
    loop(Socket) ->
    receive
    {tcp,Socket,Data} -> … 输出处理 …
    {tcp_closed,Socket} -> …
    end.
    这个过程无法控制发到服务器循环的消息流,如果客户端产生数据的速度大于服务器消费数据的速度,系统就会收到洪水般地消息-消息缓冲区溢出,系统将会crash并表现怪异。
    这种类型的服务器叫做非阻塞服务器,因为它无法阻塞客户端。我们仅在信任客户端的情况下才会使用非阻塞服务器。

    2 被动消息获取(阻塞)
    在这一节,我们写阻塞服务器:服务器以被动模式打开socket,通过 {active,false} 选项。这个服务器不会被危险的客户端洪水袭击。
    服务器循环中的代码调用 gen_tcp:recv 来接收数据。客户端在服务器调用 recv 之前会被阻塞。注意OS会对客户端发来的数据做一下缓冲,以允许客户端在服务器调用 recv 之前仍然可以继续发送一小段数据。
    {ok,Listen} = gen_tcp:listen(Port,[…,{active,false}…]),
    {ok,Socket} = gen_tcp:accept(Listen), loop(Socket).
    loop(Socket) ->
    case gen_tcp:recv(Socket,N) of {ok,B} -> … 数据处理 … loop(Socket);
    {error,closed} …
    end.

    3 混合消息获取(部分阻塞)
    你可能认为把被动模式用到所有服务器上都合适。不幸的是,当我们在被动模式时,我们只能等待来自于一个socket的数据。这对于需要等待多个socket来源数据的服务器则不适用。
    幸运的是我们可以用混合方式,既不是阻塞的也不是非阻塞的。我们以一次主动(active once)模式 {active,once} 打开socket。在这个模式中,socket是主动的,但是只能接收一条消息。在控制进程发出一条消息之后,他必须明确的调用 inet:setopts 以便让socket恢复并接收下一条消息。系统在这发生之前会一直阻塞。这是两种世界的最好结合点。如下是代码:
    {ok,Listen} = gen_tcp:listen(Port,[…,{active,once}…]),
    {ok,Socket} = gen_tcp:accept(Listen), loop(Socket).
    loop(Socket) ->
    receive
    {tcp,Socket,Data} -> … 数据处理 … %%准备好启用下一条消息时
    inet:setopts(Socket,[{active,once}]),
    loop(Socket);
    {tcp_closed,Socket} -> …
    end.
    使用 {active,once} 选项,用户可以实现高层次的数据流控制(有时叫交通管制),同时又防止了服务器被过多的消息洪水所淹没。

    相关文章

      网友评论

          本文标题:Erlang Socket消息获取模式主动 被动 混合

          本文链接:https://www.haomeiwen.com/subject/xdrmlttx.html