ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

我的erlang TCP服务器

2021-05-01 07:01:53  阅读:146  来源: 互联网

标签:socket stop TCP server start 服务器 erlang options Socket


不解释,直接贴代码。

1) socket_options.hrl

-record(socket_options,
        {port=8024,
         loop,
         name,
         ip=any,
         nodelay=false,
         backlog=128,
         listen=null,                
         active_sockets=0}
		).

2)  test_server.erl


-module(test_server).
-export([start/0, stop/0, looper/1]).

-include("socket_options.hrl").

%开启服务
start()->
  test_socket_server:start(#socket_options{loop = {?MODULE, looper}}).

%关闭服务
stop()->
  test_socket_server:stop(). 

looper(Socket) ->
    inet:setopts(Socket, [{active, once}]),
    receive
    {tcp, Socket, Data} ->
        io:format("Got packet: ~p~n", [Data]),
        gen_tcp:send(Socket, Data),
        looper(Socket);
    {tcp_closed, Socket}->
        io:format("Socket ~p closed~n", [Socket]);
    {tcp_error, Socket, Reason} ->
        io:format("Error on socket ~p reason: ~p~n", [Socket, Reason])
    end.


3) test_socket_server.erl


-module(test_socket_server).

-export([start/0, start/1, stop/0, stop/1]).
-export([init/1, handle_call/3, handle_cast/2, terminate/2, code_change/3,
         handle_info/2]).

-include("socket_options.hrl").

-define(RECBUF_SIZE, 8192).

start() ->
	gen_server:start(?MODULE, [], []).
start(InitArg = #socket_options{name = Name}) ->
    case Name of
        undefined ->
	    gen_server:start({local,?MODULE}, ?MODULE, InitArg, []);
        _ ->
            gen_server:start({local,Name}, ?MODULE, InitArg, [])
	end.

stop() ->
  gen_server:cast(?MODULE, stop).

stop(Name) when is_atom(Name) ->
    gen_server:cast(Name, stop);
stop(Pid) when is_pid(Pid) ->
    gen_server:cast(Pid, stop);
stop(_State = #socket_options{name = Name}) ->
    stop(Name).


%回调函数
%init(State = #socket_options{ip = Ip, port = Port, backlog = Backlog, nodelay = NoDelay}) ->
init(State = #socket_options{port = Port, backlog = Backlog, nodelay = NoDelay}) ->
    BaseOpts = [binary,
        {reuseaddr, true},
        {packet, 0},
        {backlog, Backlog},
        {recbuf, ?RECBUF_SIZE},
        {active, false},
        {nodelay, NoDelay}],
    listen(Port, BaseOpts, State).    %%监听        
 
handle_call(_Msg, _Caller, State) -> {noreply, State}.
	
handle_info(_Msg, Library) -> {noreply, Library}.

terminate(Reason, #socket_options{listen = Listen}) ->
    io:format("socket close,~p~n",[Reason]),
    gen_tcp:close(Listen).             %%关闭Listen

code_change(_OldVsn, State, _Extra) ->
    State.

handle_cast({accepted, _Pid}, State = #socket_options{active_sockets = ActiveSockets, 
            listen = Listen, loop = Loop}) ->
    NewState = State#socket_options{active_sockets = 1 + ActiveSockets},
    test_socket_server_acceptor:start_link(self(), Listen, Loop),
    {noreply, NewState};
 
handle_cast(stop, Name) ->
     %io:format("关闭服务器!~n"),
    {stop, normal , Name}.
 
listen(Port, Opts, State) ->
    case gen_tcp:listen(Port, Opts) of
        {ok, Listen} ->
			test_socket_server_acceptor:start_link(self(), Listen, State#socket_options.loop),
			NewState = State#socket_options{listen = Listen},
			{ok, NewState};
        {error, Reason} ->
            {stop, Reason}
    end.

 4) test_socket_server_acceptor.erl



-module(test_socket_server_acceptor).
-export([start_link/3, init/3]).

start_link(Server, Listen, Loop) ->
    proc_lib:spawn_link(?MODULE, init, [Server, Listen, Loop]).

init(Server, Listen, Loop) ->
    case catch gen_tcp:accept(Listen) of
        {ok, Socket} ->
            gen_server:cast(Server, {accepted, self()}),
            call_loop(Loop, Socket);
        {error, closed} ->
            exit(normal);
        {error, timeout} ->
            init(Server, Listen, Loop);
        {error, esslaccept} ->
            exit(normal);
        _ ->
            exit({error, accept_failed})
    end.

call_loop({M, F}, Socket) ->
    io:format("socket call_loop,~n"),
    M:F(Socket);
call_loop({M, F, [A1]}, Socket) ->
    M:F(Socket, A1);
call_loop({M, F, A}, Socket) ->
    erlang:apply(M, F, [Socket | A]);
call_loop(Loop, Socket) ->
    Loop(Socket).

下一步是想在此基础上写一个聊天室什么的,不过我目前我想先实践完OTP实战这本书。


标签:socket,stop,TCP,server,start,服务器,erlang,options,Socket
来源: https://blog.51cto.com/huanghongqiao/2748321

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有