欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Erlang--TCP学习(五)总结篇

程序员文章站 2022-05-18 13:11:40
...
一、erlang socket的消息流的三种控制方式:
  1 主动模式 {active, true}
  2 被动模式 {active, false}
  3 混合模式 {active, once}

1 主动消息获取(非阻塞)
  在该模式下,无法控制发到服务端的消息流,如果客户端生产消息的速度大于服务端消费消息的速度,会导致服务端消息缓冲区溢出
{ok, ListenSocket} = gen_tcp:listen(Port, [...,{active,true}...],
{ok, Socket} = gen_tcp:accept(ListenSocket}
loop_receive(Socket).

loop_receive(Socket) ->
    receive
        {tcp, Socket, Bin} ->
            ...
            loop_receive(Socket);
        {tcp_closed, Socket} ->
            ...
    end. 


2 被动消息获取(阻塞)
  被动模式下,每收到一条信息,进行阻塞,防止危险客户端消息洪水的袭击
{ok, ListenSocket} = gen_tcp:listen(Port, [...,{active,false}...],
{ok, Socket} = gen_tcp:accept(ListenSocket}
loop_receive(Socket).

loop_receive(Socket) ->
    case gen_tcp:recv(Socket, N) of
        {ok, Packet} ->
            ...
            loop_receive(Socket);
        {error, reason} ->
            ...
    end. 

  服务器调用gen_tcp:recv来接收数据,客户端在服务端调用recv前被阻塞

3 混合模式(半阻塞)
  服务器以一次主动模式{active,once}接收且仅能接收一条消息,在接收消息后,必须明确调用inet:setopts恢复socket来接收下一条消息。系统在这发生前,一直处于阻塞状态
{ok, ListenSocket} = gen_tcp:listen(Port, [...,{active,once}...],
{ok, Socket} = gen_tcp:accept(ListenSocket}
loop_receive(Socket).

loop_receive(Socket) ->
    receive
        {tcp, Socket, Bin} ->
            ...
            inet:setopts(Socket,[{active,once}]),
            loop_receive(Socket);
        {tcp_closed, Socket} ->
            ...
    end. 


二、socket的控制进程
  创建socket的进程(调用gen_tcp:accept或gen_tcp:connect)叫做这个socket的控制进程,所有来自socket的消息都会被发送到控制进程,如果控制进程死掉,对应的socket会被关闭,
可以通过gen_tcp:controlling_process(Socket, Pid)来修改socket的控制进程。