erlang分布式入门(四)-TCP Server的详解与改进
在上一篇实现的erlang分布式入门(三)-TCP Server-Client中的accept函数如下:
?
以下是改进版的TCP服务端:
?
echo_server.erl
%% a generic tcp server-module(generic_server).-author('cheng litaocheng@gmail.com').-vsn('0.1').-behaviour(gen_server).-define(TCP_OPTIONS, [binary, {packet, raw}, {active, false}, {reuseaddr, true}]).-record(server_state, { port, % listen port loop, % the logic fun ip=any, % ip lsocket=null, % listen socket conn=0, % curent connect maxconn % max connect }).%% internal export-export([init/1, handle_call/3, handle_cast/2, handle_info/2, code_change/3, terminate/2]).%% start tcp server -export([start/4]).-export([accept_loop/5]).%% start the generic serverstart(Name, Port, Max, Loop) -> State = #server_state{port=Port, loop=Loop, maxconn=Max}, io:format("max connection is ~p~n", [Max]), gen_server:start_link({local, Name}, ?MODULE, State, []).%% create listen socketinit(State = #server_state{port=Port}) -> case gen_tcp:listen(Port, ?TCP_OPTIONS) of {ok, LSocket} -> {ok, accept(State#server_state{lsocket=LSocket})}; {error, Reason} -> {stop, {create_listen_socket, Reason}} end.%% accept spawn a new processaccept(State =#server_state{lsocket=LSocket, loop=Loop, conn=Conn, maxconn=Max}) -> proc_lib:spawn(generic_server, accept_loop, [self(), LSocket, Loop, Conn, Max]), State.%% accept the new connectionaccept_loop(Server, LSocket, {M, F}, Conn, Max) -> {ok, Sock} = gen_tcp:accept(LSocket), if Conn + 1 > Max -> io:format("reach the max connection~n"), gen_tcp:close(Sock); true -> gen_server:cast(Server, {accept_new, self()}), M:F(Sock) end.%% the server receive the notify that a connect has constructhandle_cast({accept_new, _Pid}, State=#server_state{conn=Cur}) -> io:format("current connect:~p~n", [Cur+1]), {noreply, accept(State#server_state{conn=Cur+1})};%% someone connect has been close, so change the max connecthandle_cast({connect_close, _Pid}, State=#server_state{conn=Cur}) -> io:format("current connect:~p~n", [Cur-1]), {noreply, State#server_state{conn=Cur-1}}.handle_call(_From, _Request, State) -> {noreply, State}.handle_info(_Info, State) -> {noreply, State}.code_change(_OldVsn, State, _Extra) -> {ok, State}.terminate(_Reason, _State) -> ok.?主要使用了erlang的gen_server内置函数,详解:http://www.erlang.org/doc/design_principles/gen_server_concepts.html