erlang高性能网络库esockd的编译和使用(三)-keepalive
来源:互联网 发布:女白色t恤淘宝店铺推荐 编辑:程序博客网 时间:2024/06/11 13:54
在上一篇基础上,继续完善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%% APIstart() -> 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 Callbacksstart_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
阅读全文
0 0
- erlang高性能网络库esockd的编译和使用(三)-keepalive
- erlang高性能网络库esockd的编译和使用(一)
- erlang高性能网络库esockd的编译和使用(二)-application
- erlang高性能网络库esockd的编译和使用(四)-env
- erlang高性能网络库esockd的编译和使用(五)-热更新
- 高性能网络编程(三)----TCP消息的接收
- 高性能网络编程(三)----TCP消息的接收
- 计算机网络探究(三) TCP和HTTP的keepAlive
- 计算机网络探究(三) TCP和HTTP的keepAlive
- 优秀开源项目之三:高性能、高并发、高扩展性和可读性的网络服务器架构State Threads
- 优秀开源项目之三:高性能、高并发、高扩展性和可读性的网络服务器架构State Threads
- Erlang语言 基于LLVM的高性能Erlang(Hipe)尝鲜
- Erlang语言 基于LLVM的高性能Erlang(Hipe)尝鲜
- erlang节点间通信使用erlang send 和使用gen_tcp socket性能的对比(
- 从ZooKeeper源代码看如何实现分布式系统(三)高性能的网络编程
- 大型网站系统架构实践(三)如何提高网站的高可用和高性能
- (三)创建高性能的索引
- libevent高性能网络库源码分析——事件(event)及其接口(三)
- Windows平台安装Hadoop
- sendSubviewToBack和bringSubviewToFront
- tensorflow入门之mnist手写数据集识别
- MongoDB 创建地图索引及根据位置坐标查询地点小例子
- CSS3的几个属性和文字翻页效果练习
- erlang高性能网络库esockd的编译和使用(三)-keepalive
- Java基本类型计算不准时,防坑妙招
- 03JXV支持分布式集群部署
- java学习之ArrayList容器类详解
- apply、call和bind的区别
- HashSet 对象去重复处理
- intellij idea怎么创建maven项目
- 【我的Java笔记】常用类_Character
- 2.14子数组之和最大