Erlang简单并行服务器

(金庆的专栏)

Erlang并行服务器为每一个Tcp连接创建相应的连接进程,处理client数据。

參考 Erlang程序设计(第2版)
17.1.3 顺序和并行服务器

并行服务器的诀窍是:每当gen_tcp:accept收到一个新连接时就马上分裂一个新进程。

为每一个新套接字连接创建一个并行进程。

-module(gs_svr).
-author("jinqing").

-behaviour(gen_server).

%% API
-export([start_link/0]).

init([]) ->
    gs_listener:start_parallel(),
    {ok, #{}}.

gs_svr(GameServer gen_server)启动Tcp监听。并维护连接,如连接计数,发送广播。

start_parallel()创建监听端口,然后创建连接进程。

start_parallel() ->
    Port = server_csv:get_my_port(),
    lager:info("Starting game server on port ~p...", [Port]),
    {ok, ListenSocket} = gen_tcp:listen(Port,
        [binary, {packet, 4},
            {packet_size, 256 * 1024},  % limit packet size
            {reuseaddr, true},
            {nodelay, true},
            {backlog, 999999},
            {active, once}]),
    connection:spawn_connection(ListenSocket).

spawn_connection()创建连接进程。每接受一个连接就再创建一个新的连接进程。

-module(connection).
-author("jinqing").

%% API
-export([spawn_connection/1]).
-export([parallel_connect/1, loop/2]).

-spec spawn_connection(ListenSocket :: gen_tcp:socket()) -> pid().
spawn_connection(ListenSocket) ->
    spawn(fun() -> ?

MODULE:parallel_connect(ListenSocket) end).

-spec parallel_connect(ListenSocket :: gen_tcp:socket()) -> ok.
parallel_connect(ListenSocket) ->
    {ok, Socket} = gen_tcp:accept(ListenSocket),
    spawn_connection(ListenSocket),
    
    gs_svr:cast_connection_new(self()),
    ConnStat = conn_stat:new(),
    erlang:send_after(1000, self(), timer_sec),
    try ?MODULE:loop(Socket, ConnStat)
    catch
        Type:E -> lager:error("loop() ~p:~p. ~p",
            [Type, E, erlang:get_stacktrace()])
    end,
    gs_svr:cast_connection_ended(self()),
    ok.

-spec loop(Socket :: gen_tcp:socket(), ConnStat :: conn_stat:conn_stat()) -> any().
loop(Socket, ConnStat) ->
    receive
        {tcp, Socket, Bin} ->
            NewConnStat = rpc_handler:handle_bin(Socket, Bin, ConnStat),
            inet:setopts(Socket, [{active, once}]),
            NewConnStat2 = cutil_dos_checker:on_data(size(Bin), NewConnStat),
            ?MODULE:loop(Socket, NewConnStat2#{idle_sec=>0});
        {tcp_closed, Socket} ->
            save_on_end(ConnStat);
        {tcp_error, Socket, Reason} ->
            save_on_end(ConnStat);

{gs_to_connection, Msg} ->
            NewConnStat = handle_gs_msg(Msg, Socket, ConnStat),
            ?MODULE:loop(Socket, NewConnStat);

timer_sec ->
            case conn_timer:timer_sec(ConnStat) of
                {ok, NewConnStat} ->
                    erlang:send_after(1000, self(), timer_sec),
                    ?MODULE:loop(Socket, NewConnStat);
            end;
        Other ->
            lager:error("Unknown msg: ~p", [Other]),
            ?MODULE:loop(Socket, ConnStat)
    end.  % This is tail-recursive.

缺点是连接进程没有增加监控树。

gs_svr出错重新启动时,连接进程connection应该断开并退出。

Erlang简单并行server的更多相关文章

  1. Erlang简单并行服务器

    Erlang简单并行服务器(金庆的专栏)Erlang并行服务器为每个Tcp连接创建对应的连接进程,处理客户端数据.参考 Erlang程序设计(第2版)17.1.3 顺序和并行服务器并行服务器的诀窍是: ...

  2. Ubuntu下erlang连接SQL SERVER 2008

    erlang连接SQL Server使用ODBC方法,但在网络上还是缺少资料,自己折腾了2天才成功.现在特记录下来,以供大家借鉴. 基本思路是 erlang odbcserver + unixodbc ...

  3. 为什么我要选择erlang+go进行server架构(2)

    原创文章,转载请注明出处:server非业余研究http://blog.csdn.net/erlib 作者Sunface 为什么我要选择Erlang呢? 一.erlang特别适合中小团队创业: erl ...

  4. spring cloud 创建一个简单Eureka Server

    在Spring Cloud实现一个Eureka Server是一件非常简单的事情.下面我们来写一个Eureka Server DEMO. 编码 父项目pom.xml <?xml version= ...

  5. 使用HANA Web-based Development Workbench创建最简单的Server Side JavaScript

    服务器端的JavaScript, 看下wikipedia的介绍: https://en.wikipedia.org/wiki/JavaScript#Server-side_JavaScript Ser ...

  6. Tomcat是怎么工作的(2) -- 动手实现山寨版的简单Web Server

    本文先讲解一下Java web server都是怎么工作的.web server也叫HTTP server——顾名思义它是用HTTP协议和客户端交互的.客户端一般就是各种各样的浏览器了.相信所有朋友都 ...

  7. Slickflow.NET 开源工作流引擎快速入门之二: 简单并行分支流程代码编写示例

    前言:对于急切想了解引擎功能的开发人员,在下载版本后,就想尝试编写代码,完成一个流程的开发和测试.本文试图从一个最简单的并行分支流程来示例说明,如何快速了解引擎代码的编写. 版本:.NET Core2 ...

  8. 写一个最简单的 Server

    import java.net.*;import java.io.*;public class Server{ public static void main(String[] args) throw ...

  9. asp.net Socket的简单Web Server

    1.首先初始化socket,包含对端点以及对连接队列长度的初始化 IPAddress address = IPAddress.Loopback; IPEndPoint endPoint = ); So ...

随机推荐

  1. Vue小技巧,如何导入普通JS文件

    最近在开发一个展示3D模型的WEB程序,在工程中使用了VUE和ThreeJS库.Three.js本身是支持CommonJS的,但我们还用到了OBJLoader模块,此模块不支持CommonJS,改成C ...

  2. Android sdk版本以及兼容性问题

    Android:minSdkVersion —— 此属性决定你的应用能兼容的最低的系统版本,一盘情况是必须设置此属性. android:targetSdkVersion —— 此属性说明你当前的应用是 ...

  3. SSRS 报表 如何匿名查看

    SSRS 报表 如何匿名查看 昨晚一直研究怎么能匿名访问报表然后给客户看呢? 研究了好几种办法 我试过的分为三种,其中推荐我认为相对可控一点. .修改SSRS配置文件来禁止他验证登陆用户权限 操作过的 ...

  4. CSS命令

    border-bottom-right-radius: 10px;/* 文本框的角的弯曲度*/ border-bottom-left-radius: 10px; border-top-left-rad ...

  5. [POI2008]POD-Subdivision of Kingdom(搜索+状压)

    题意 给定一个n个点的无向图,要求将点集分成大小相等的两个子集,使两个子集之间的边数最少 (n<=26) 题解 一开始想了半天DP发现不会,去看题解全是搜索. 所以发现C(1326)可以过我就写 ...

  6. 【转载】Perl中字符串编码的处理

    在 Perl看来, 字符串只有两种形式. 一种是octets, 即8位序列, 也就是我们通常说的字节数组. 另一种utf8编码的字符串, perl管它叫string. 也就是说: Perl只熟悉两种编 ...

  7. caioj 1069 动态规划入门(二维一边推2:顺序对齐)(最长公共子序列拓展总结)

    caioj 1068是最长公共子序列裸体,秒过, 就不写博客了 caioj 1069到1071 都是最长公共字序列的拓展,我总结出了一个模型,屡试不爽    (1) 字符串下标从1开始,因为0用来表示 ...

  8. wpf convert png to xaml

    原文:wpf convert png to xaml 把png图片转化成xaml资源 <ResourceDictionary xmlns="http://schemas.microso ...

  9. ECNUOJ 2574 Principles of Compiler

    Principles of Compiler Time Limit:1000MS Memory Limit:65536KBTotal Submit:473 Accepted:106 Descripti ...

  10. spring的PropertyPlaceholderConfigurer不生效的问题

    经常出现这种问题,每次都debug知道原因,但每次都会忘记,所以记录一下. 原因:maven项目中使用了非maven管理的jar包(通过systemPath引用),这些jar包没有放在${projec ...