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 

相关文章
|
5月前
|
网络协议 算法 Java
基于Reactor模型的高性能网络库之Tcpserver组件-上层调度器
TcpServer 是一个用于管理 TCP 连接的类,包含成员变量如事件循环(EventLoop)、连接池(ConnectionMap)和回调函数等。其主要功能包括监听新连接、设置线程池、启动服务器及处理连接事件。通过 Acceptor 接收新连接,并使用轮询算法将连接分配给子事件循环(subloop)进行读写操作。调用链从 start() 开始,经由线程池启动和 Acceptor 监听,最终由 TcpConnection 管理具体连接的事件处理。
216 2
|
5月前
基于Reactor模式的高性能网络库github地址
https://github.com/zyi30/reactor-net.git
140 0
|
3月前
|
监控 前端开发 安全
Netty 高性能网络编程框架技术详解与实践指南
本文档全面介绍 Netty 高性能网络编程框架的核心概念、架构设计和实践应用。作为 Java 领域最优秀的 NIO 框架之一,Netty 提供了异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。本文将深入探讨其 Reactor 模型、ChannelPipeline、编解码器、内存管理等核心机制,帮助开发者构建高性能的网络应用系统。
238 0
|
4月前
|
机器学习/深度学习 算法 数据库
基于GoogleNet深度学习网络和GEI步态能量提取的步态识别算法matlab仿真,数据库采用CASIA库
本项目基于GoogleNet深度学习网络与GEI步态能量图提取技术,实现高精度步态识别。采用CASI库训练模型,结合Inception模块多尺度特征提取与GEI图像能量整合,提升识别稳定性与准确率,适用于智能安防、身份验证等领域。
|
12月前
|
SQL 安全 网络安全
网络安全与信息安全:知识分享####
【10月更文挑战第21天】 随着数字化时代的快速发展,网络安全和信息安全已成为个人和企业不可忽视的关键问题。本文将探讨网络安全漏洞、加密技术以及安全意识的重要性,并提供一些实用的建议,帮助读者提高自身的网络安全防护能力。 ####
273 17
|
SQL 安全 网络安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
随着互联网的普及,网络安全问题日益突出。本文将从网络安全漏洞、加密技术和安全意识三个方面进行探讨,旨在提高读者对网络安全的认识和防范能力。通过分析常见的网络安全漏洞,介绍加密技术的基本原理和应用,以及强调安全意识的重要性,帮助读者更好地保护自己的网络信息安全。
231 10
|
存储 SQL 安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
随着互联网的普及,网络安全问题日益突出。本文将介绍网络安全的重要性,分析常见的网络安全漏洞及其危害,探讨加密技术在保障网络安全中的作用,并强调提高安全意识的必要性。通过本文的学习,读者将了解网络安全的基本概念和应对策略,提升个人和组织的网络安全防护能力。
|
SQL 安全 网络安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
在数字化时代,网络安全和信息安全已成为我们生活中不可或缺的一部分。本文将介绍网络安全漏洞、加密技术和安全意识等方面的内容,并提供一些实用的代码示例。通过阅读本文,您将了解到如何保护自己的网络安全,以及如何提高自己的信息安全意识。
242 10
|
监控 安全 网络安全
网络安全与信息安全:漏洞、加密与意识的交织
在数字时代的浪潮中,网络安全与信息安全成为维护数据完整性、保密性和可用性的关键。本文深入探讨了网络安全中的漏洞概念、加密技术的应用以及提升安全意识的重要性。通过实际案例分析,揭示了网络攻击的常见模式和防御策略,强调了教育和技术并重的安全理念。旨在为读者提供一套全面的网络安全知识框架,从而在日益复杂的网络环境中保护个人和组织的资产安全。
|
存储 监控 安全
云计算与网络安全:云服务、网络安全、信息安全等技术领域的融合与挑战
本文将探讨云计算与网络安全之间的关系,以及它们在云服务、网络安全和信息安全等技术领域中的融合与挑战。我们将分析云计算的优势和风险,以及如何通过网络安全措施来保护数据和应用程序。我们还将讨论如何确保云服务的可用性和可靠性,以及如何处理网络攻击和数据泄露等问题。最后,我们将提供一些关于如何在云计算环境中实现网络安全的建议和最佳实践。

热门文章

最新文章