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的控制进程。