英雄遠征Erlang源碼分析(2)-網關服務器的啓動

上一篇文章解析了遊戲源碼的結構,我們知道該源碼包含兩個服務器的啓動腳本:網關服務器和遊戲服務器,其中網關服務器用於在玩家選擇進入遊戲服務器之前獲取服務器列表,遊戲服務器則處理玩家進入遊戲服務器後的登錄,進入遊戲操作。

先來說說遊戲的網關服務器部分的啓動過程,和網關服務器相關的代碼爲sd_gateway_xxx.erl。

運行script/gateway.sh文件,從sd:gateway_start/0部分啓動名爲gateway的應用,找到gateway.app中的{mod,{sd_gateway_app,[]}},進入sd_gateway_app:start/2,進行初始化數據庫,啓動sd_gateway_sup監控樹的操作。

進入sd_gateway_sup,在監控樹下掛兩個進程:sd_gateway和mod_disperse,前者爲網關的具體實現通過循環等待來自客戶端的tcp連接,處理協議號爲60000和60001的請求(具體協議內容可以查看doc/60網關協議.txt);後者爲在有新的節點加入集羣時進行通知,在遊戲服務器部分也有應用,此處先不展開說明。

從sd_gateway:init/1進入,可以發現其調用了sd_gateway_server;start_raw_server/3方法,其代碼如下:

start_raw_server(Port, Fun, Max) ->
	Name = port_name(Port),
	case whereis(Name) of
            undefined ->
                Self = self(),
                Pid = spawn(fun() -> code_start(Self, Port, Fun, Max) end),
                receive
                    {Pid, ok} ->
                        register(Name, Pid);
                        ...

首先判斷端口名稱是否已經被註冊,沒有的話,則創建一個調用code_start/3函數的進程,用於打開端口的監聽,接收來自客戶端的消息並處理,如果該進程創建成功,則註冊該網關節點的名稱。

code_start/3函數如下:

code_start(Master, Port, Fun, Max) ->
	process_flag(trap_exit, true),
	case gen_tcp:listen(Port, ?TCP_OPTIONS) of
            {ok,Listen} ->
                Master ! {self(), ok},
                New = start_accept(Listen, Fun),
                socket_loop(Listen, New, [], Fun, Max);
            Error ->
                Master ! {self(), Error}
    end.

函數先是使用gen_tcp:listen/2建立對端口的監聽,然後分爲兩部分:1.使用start_accept/2創建接收客戶端Socket消息的進程。2.使用socket_loop/5進行接收客戶端Socket連接進程池的維護。

與客戶端連接進程的創建通過start_accept/2實現。將ListenSocket傳入start_accept/2,在start_accept/2中創建使用gen_tcp:accept/1等待並創建和客戶端的Socket連接的進程,獲取Socket連接後,傳入sd_gateway:handoff/2進行協議的處理(主要是處理60000獲取服務器列表,60001判斷角色是否創建)。

進程池的維護通過socket_loop/5的尾遞歸循環實現。當有新的客戶端Socket連接進來後,通過prossibly_start_another/5開啓新的客戶端Socket等待進程;如果客戶端Socket斷開了,進程池會從維護的進程列表中刪掉該進程的Pid;如果連接進程數量達到了上限,則會發出警告。

協議處理完之後會關閉該Socket,此時客戶端已經獲取了遊戲服務器的IP和端口列表,可以去連接遊戲服務器了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章