erlang高性能网络库esockd的编译和使用(三)-keepalive

简介: erlang高性能网络库esockd的编译和使用(三)-keepalive

在上一篇基础上,继续完善app。新增心跳检测机制。

修改文件echo_server.erl如下:

-module(echo_server).
-include("../deps/esockd/include/esockd.hrl").
-behaviour(gen_server).
%% start
-export([start/0, start/1]).
-export([start_link/1]).
%% gen_server Function Exports
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
         terminate/2, code_change/3]).
-record(state, {conn, connname, peername, peerhost, peerport, keepalive}).
-define(TCP_OPTIONS, [
  binary,
        {packet, raw},
        {buffer, 1024},
  {reuseaddr, true},
  {backlog, 512},
  {nodelay, false}]).
-define(TCP_PORT, 5000).
-define(TIMEOUT_SEC, 30).%unit:s
%% API
start() ->
    start(?TCP_PORT).
start([Port]) when is_atom(Port) ->
    start(list_to_integer(atom_to_list(Port)));
start(Port) when is_integer(Port) ->
    %% application:start(sasl),
    %% ok = esockd:start(),
    Access = application:get_env(esockd, access, [{allow, all}]),
    SockOpts = [{access, Access},
                {acceptors, 32},
                {max_clients, 1000000},
                {sockopts, ?TCP_OPTIONS}],
    MFArgs = {?MODULE, start_link, []},
    esockd:open(echo, Port, SockOpts, MFArgs).
%% eSockd Callbacks
start_link(Conn) ->
    {ok, proc_lib:spawn_link(?MODULE, init, [Conn])}.
init(Conn) ->
    {ok, Conn1} = Conn:wait(),
    {PeerHost, PeerPort, PeerName} =
    case Conn1:peername() of
        {ok, Peer = {Host, Port}} ->
            {Host, Port, Peer};
        {error, enotconn} ->
            Conn1:fast_close(),
            exit(normal);
        {error, Reason} ->
            Conn1:fast_close(),
            exit({shutdown, Reason})
    end,
    ConnName = esockd_net:format(PeerName),
    %%io:format("~s~n", [esockd_net:format(peername, PeerName)]),
    io:format("tcp_connected,~s~n", [esockd_net:format({PeerHost, PeerPort})]),
    start_keepalive(?TIMEOUT_SEC),
    Conn1:setopts([{active, once}]),
    gen_server:enter_loop(?MODULE, [], #state{conn       = Conn1,
                                              connname   = ConnName,
                                              peername   = PeerName,
                                              peerhost   = PeerHost,
                                              peerport   = PeerPort}).
handle_call(_Request, _From, State) ->
    {reply, ok, State}.
handle_cast(_Msg, State) ->
    {noreply, State}.
handle_info({tcp, Sock, Data}, State = #state{conn = ?ESOCK(Sock) = Conn}) ->
    {ok, PeerName} = Conn:peername(),
    io:format("~s - ~s~n", [esockd_net:format(peername, PeerName), Data]),
    Conn:send(Data),
    Conn:setopts([{active, once}]),
    {noreply, State};
handle_info({tcp_error, Sock, Reason}, State = #state{conn = ?ESOCK(Sock)}) ->
    io:format("tcp_error: ~s~n", [Reason]),
    {stop, {shutdown, {tcp_error, Reason}}, State};
handle_info({tcp_closed, Sock}, State = #state{conn = ?ESOCK(Sock), peername = PeerName}) ->
    io:format("tcp_closed,~s~n", [esockd_net:format(peername, PeerName)]),
    {stop, normal, State};
handle_info({keepalive, start, Interval}, State = #state{conn = Conn1}) ->
    io:format("Keepalive at the interval of ~p~n", [Interval]),
    {ok, KeepAlive} = esockd_keepalive:start(Conn1, Interval, {keepalive, check}),
    hibernate(State#state{keepalive = KeepAlive});
handle_info({keepalive, check}, State = #state{peername = PeerName, keepalive = KeepAlive}) ->
    io:format("Keepalive check,~s,", [esockd_net:format(peername, PeerName)]),
    case esockd_keepalive:resume(KeepAlive) of
        {resumed, KeepAlive1} ->
            io:format("Keepalive resumed~n"),
            hibernate(State#state{keepalive = KeepAlive1});
        {error, timeout} ->
            io:format("Keepalive timeout~n"),
            shutdown(keepalive_timeout, State);
        {error, Error} ->
            io:format("Keepalive error - ~p~n", [Error]),
            shutdown(Error, State)
    end;
handle_info(_Info, State) ->
    {noreply, State}.
%terminate(_Reason, _State) ->
%    ok.
terminate(_Reason, #state{conn     = Conn1,
                         keepalive = KeepAlive}) ->
    Conn1:fast_close(),
    esockd_keepalive:cancel(KeepAlive),
    ok.
code_change(_OldVsn, State, _Extra) ->
    {ok, State}.
%%--------------------------------------------------------------------
%% Internal functions
%%--------------------------------------------------------------------
start_keepalive(0) -> ignore;
start_keepalive(Sec) when Sec > 0 ->
    self() ! {keepalive, start, round(Sec * 1.20)}.
hibernate(State) ->
    {noreply, State, hibernate}.
shutdown(Reason, State) ->
    stop({shutdown, Reason}, State).
stop(Reason, State) ->
    {stop, Reason, State}.

如果想知道当前客户端的数目,可以在init函数实现:

init(Conn) ->
    {ok, Conn1} = Conn:wait(),
    {PeerHost, PeerPort, PeerName} =
    case Conn1:peername() of
        {ok, Peer = {Host, Port}} ->
            {Host, Port, Peer};
        {error, enotconn} ->
            Conn1:fast_close(),
            exit(normal);
        {error, Reason} ->
            Conn1:fast_close(),
            exit({shutdown, Reason})
    end,
    ConnName = esockd_net:format(PeerName),
    %%io:format("~s~n", [esockd_net:format(peername, PeerName)]),
    io:format("tcp_connected,~s~n", [esockd_net:format({PeerHost, PeerPort})]),
    start_keepalive(?TIMEOUT_SEC),
    Conn1:setopts([{active, once}]),
    %% method 1:
    lists:foreach(fun({{Protocol, ListenOn}, Pid}) ->
                Info = [{acceptors,      esockd:get_acceptors(Pid)},
                        {max_clients,    esockd:get_max_clients(Pid)},
                        {current_clients,esockd:get_current_clients(Pid)},
                        {shutdown_count, esockd:get_shutdown_count(Pid)}],
                io:format("listener on ~s:~s~n", [Protocol, esockd:to_string(ListenOn)]),
                lists:foreach(fun({Key, Val}) ->
                            io:format("  ~-16s: ~w~n", [Key, Val])
                        end, Info)
            end, esockd:listeners()),
    %% method 2:
    Pid1 = esockd:listener({echo, ?TCP_PORT}),
    Count1 = esockd:get_current_clients(Pid1),
    io:format("current_clients:~p~n", [Count1]),
    %% method 3:
    Count2 = esockd:get_current_clients({echo, ?TCP_PORT}),
    io:format("current_clients:~p~n", [Count2]),
    gen_server:enter_loop(?MODULE, [], #state{conn       = Conn1,
                                              connname   = ConnName,
                                              peername   = PeerName,
                                              peerhost   = PeerHost,
                                              peerport   = PeerPort}).

完整的源码下载地址: http://download.csdn.net/download/libaineu2004/10113319 

相关文章
|
3天前
|
编解码 分布式计算 网络协议
Netty高性能网络框架(一)
Netty高性能网络框架(一)
|
5天前
|
JavaScript 前端开发 API
网络请求库 – axios库
网络请求库 – axios库
|
7天前
|
数据采集 JSON API
🎓Python网络请求新手指南:requests库带你轻松玩转HTTP协议
本文介绍Python网络编程中不可或缺的HTTP协议基础,并以requests库为例,详细讲解如何执行GET与POST请求、处理响应及自定义请求头等操作。通过简洁易懂的代码示例,帮助初学者快速掌握网络爬虫与API开发所需的关键技能。无论是安装配置还是会话管理,requests库均提供了强大而直观的接口,助力读者轻松应对各类网络编程任务。
37 3
|
8天前
|
机器学习/深度学习 JSON API
HTTP协议实战演练场:Python requests库助你成为网络数据抓取大师
在数据驱动的时代,网络数据抓取对于数据分析、机器学习等至关重要。HTTP协议作为互联网通信的基石,其重要性不言而喻。Python的`requests`库凭借简洁的API和强大的功能,成为网络数据抓取的利器。本文将通过实战演练展示如何使用`requests`库进行数据抓取,包括发送GET/POST请求、处理JSON响应及添加自定义请求头等。首先,请确保已安装`requests`库,可通过`pip install requests`进行安装。接下来,我们将逐一介绍如何利用`requests`库探索网络世界,助你成为数据抓取大师。在实践过程中,务必遵守相关法律法规和网站使用条款,做到技术与道德并重。
21 2
|
9天前
|
数据采集 存储 JSON
从零到一构建网络爬虫帝国:HTTP协议+Python requests库深度解析
在网络数据的海洋中,网络爬虫遵循HTTP协议,穿梭于互联网各处,收集宝贵信息。本文将从零开始,使用Python的requests库,深入解析HTTP协议,助你构建自己的网络爬虫帝国。首先介绍HTTP协议基础,包括请求与响应结构;然后详细介绍requests库的安装与使用,演示如何发送GET和POST请求并处理响应;最后概述爬虫构建流程及挑战,帮助你逐步掌握核心技术,畅游数据海洋。
41 3
|
3天前
|
安全 算法 网络安全
网络安全与信息安全:构建数字世界的坚固防线在数字化浪潮席卷全球的今天,网络安全与信息安全已成为维系社会秩序、保障个人隐私和企业机密的关键防线。本文旨在深入探讨网络安全漏洞的本质、加密技术的前沿进展以及提升公众安全意识的重要性,通过一系列生动的案例和实用的建议,为读者揭示如何在日益复杂的网络环境中保护自己的数字资产。
本文聚焦于网络安全与信息安全领域的核心议题,包括网络安全漏洞的识别与防御、加密技术的应用与发展,以及公众安全意识的培养策略。通过分析近年来典型的网络安全事件,文章揭示了漏洞产生的深层原因,阐述了加密技术如何作为守护数据安全的利器,并强调了提高全社会网络安全素养的紧迫性。旨在为读者提供一套全面而实用的网络安全知识体系,助力构建更加安全的数字生活环境。
|
2天前
|
存储 安全 算法
网络安全与信息安全:守护数字世界的坚盾
在这个数字时代,网络安全已成为我们不可忽视的重要议题。本文将深入探讨网络安全漏洞的成因及影响、加密技术的工作原理与应用、以及安全意识的培养和重要性。通过这些内容的学习,读者将能够更好地理解如何保护自己的信息安全,预防潜在的网络威胁。
|
1天前
|
机器学习/深度学习 安全 网络安全
云计算时代的守护者:网络安全与信息安全的融合
在云计算的大潮中,网络安全与信息安全成为了支撑技术发展的两大支柱。本文将探讨云服务、网络安全和信息安全的相互关系,以及如何在这个互联网快速发展的时代,保护我们的数字资产。
|
1天前
|
存储 监控 安全
网络安全与信息安全:守护数字世界的钥匙
本文深入探讨了网络安全与信息安全的重要性,详细解析了网络漏洞、加密技术以及安全意识等关键领域。通过对实际案例的分析,揭示了网络安全漏洞的严重性和普遍性,强调了加密技术在保护数据安全中的核心作用,同时呼吁提升公众的安全意识,共同构建安全可靠的网络环境。
|
1天前
|
存储 安全 算法
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
本文深入探讨了网络安全和信息安全领域的关键要素,包括网络安全漏洞、加密技术和安全意识。首先,文章介绍了网络安全漏洞的定义、类型以及发现和修复过程。接着,详细阐述了加密技术的原理、应用及其在保护数据安全中的重要性。最后,强调了提高安全意识的必要性,并提供了实用的安全建议。通过综合分析这些方面,本文旨在为读者提供全面的网络安全和信息安全知识,帮助他们更好地保护自己的在线安全。