Erlang简单并行服务器

(金庆的专栏)

Erlang并行服务器为每个Tcp连接创建对应的连接进程,处理客户端数据。

参考 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简单并行服务器的更多相关文章

  1. Erlang简单并行server

    Erlang简单并行服务器 (金庆的专栏) Erlang并行服务器为每一个Tcp连接创建相应的连接进程,处理client数据. 參考 Erlang程序设计(第2版)17.1.3 顺序和并行服务器 并行 ...

  2. Erlang cowboy websocket 服务器

    Erlang cowboy websocket 服务器 原文见于: http://marcelog.github.io/articles/erlang_websocket_server_cowboy_ ...

  3. C#中使用Socket实现简单Web服务器

    上一篇博客中介绍了怎样使用socket访问web服务器.关键有两个: 熟悉Socket编程: 熟悉HTTP协议. 上一篇主要是通过socket来模拟浏览器向(任何)Web服务器发送(HTTP)请求,重 ...

  4. 用nodejs搭建一个简单的服务器

    使用nodejs搭建一个简单的服务器 nodejs优点:性能高(读写文件) 数据操作能力强 官网:www.nodejs.org 验证是否安装成功:cmd命令行中输入node -v 如果显示版本号表示安 ...

  5. 初学Node(六)搭建一个简单的服务器

    搭建一个简单的服务器 通过下面的代码可以搭建一个简单的服务器: var http = require("http"); http.createServer(function(req ...

  6. 搭建无限制权限的简单git服务器使用git-daemon脚本

    如果想要用ubantu架设无限制权限(即不适用gitosis)的简单git服务器,实现git库下载clone,push等简单的基本功能, 可以直接使用git-daemon脚本(非常不安全,建议项目代码 ...

  7. 运用socket实现简单的服务器客户端交互

    Socket解释: 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket. Socket的英文原义是“孔”或“插座”.作为BSD UNIX的进程通信机制,取后一种意 ...

  8. Ubuntu 14.04搭建简单git服务器

    /****************************************************************************** * Ubuntu 14.04搭建简单gi ...

  9. tomcat解析之简单web服务器(图)

    链接地址:http://gogole.iteye.com/blog/587163 之前有javaeyer推荐了一本书<how tomcat works>,今天晚上看了看,确实不错,第一眼就 ...

随机推荐

  1. Logistic Regression vs Naive Bayes

    相同 逻辑回归和朴素贝叶斯都是对条件概率\(P(X|y)\)进行建模,使得最终的分类结果有很好的解释性. 不同 具体流程 逻辑回归: 假设\(P(y=1|X)\)满足逻辑函数\(h(z)=1/1+ex ...

  2. 2018年Java后端面试经历

    楼主16年毕业,16年三月份进入上一家公司到今年3月底,所以这是一份两年工作经验面经分享. 都说金三银四,往些年都是听着过没啥特别的感觉.今年自己倒是确确实实体验了一把银四,从3月26裸辞到4月17号 ...

  3. [BZOJ 3456]城市规划

    Description 题库链接( bzoj 权限题,可以去 cogs 交♂ 题库链接2 求含有 \(n\) 个点有标号的简单无向联通图的个数.方案数对 \(1004535809(479\times ...

  4. ●SCOI2018 AFO

    Day2 T3代码: #include<cstdio> #include<cstring> #include<iostream> using namespace s ...

  5. Divide by Zero 2017 and Codeforces Round #399 (Div. 1 + Div. 2, combined)

    C题卡了好久,A掉C题之后看到自己已经排在好后面说实话有点绝望,最后又过了两题,总算稳住了. AC:ABCDE Rank:191 Rating:2156+37->2193 A.Oath of t ...

  6. java版的类似飞秋的局域网在线聊天项目

    原文链接:http://www.cnblogs.com/wangleiblog/articles/5323305.html 转载请注明 最近在弄一个java版的局域网在线聊天项目,功能跟飞秋差不多.p ...

  7. Linux基本知识总结

    一.Linux的基本介绍 起源:大家知道先有Unix,后有的linux就行了,其他的细节可以自己查阅资料. 特点:开源!!! 安全(Linux的病毒远少于window). 免费(商业公司最喜欢这一点) ...

  8. SpringMVC 处理映射

    一.Spring MVC控制器名称处理映射 以下示例展示如何利用Spring MVC 框架使用控制器名称处理程序映射. ControllerClassNameHandlerMapping类是基于约定的 ...

  9. 锐捷Linux版的下载和使用(福大客户端)

    下载锐捷程序包 点此下载 没有连接到锐捷里就进不了这个安装包的官方下载界面(好矛盾啊这个),所以我把它上传到博客园了. 解压文件 schaepher:~$ cd Downloads/ schaephe ...

  10. 用JavaScript按一定格式解析出URL 串中所有的参数

    1.先看看location对象 2.其中的search属性就获取当前URL的查询部分(问号?之后的部分) 3.改造location.search 比如当前URL为:https://www.hao123 ...