一起做网游吧【9】:多服务器支持

       Player3 = Client#client.player,
                    case Player3#player.server_pid of
                        none ->
                            case serverstate:call({player_join, ServerName, Client#client.player, Client#client.server_pid, self()}) of
                                {ok,{reconnect, {IP, Port, Code}}} ->
                                    Player = Client#client.player,
                                    Player2 = Player#player {
                                                tag_server = IP,
                                                tag_port = Port, 
                                                code = Code
                                               },
                                    case mnesia:transaction( fun() -> mnesia:write(Player2) end) of
                                        {atomic, ok} ->
                                            ok = ?tcpsend(Socket, {?PP_CONNECTSERVER, {IP, Port, Code}}),
                                            ok;
                                        Other->
                                            io:fomrat("server loop other:~p~p: ~p~n", [?MODULE, ?LINE, Other]),
                                            ok = ?tcpsend(Socket, {?ERROR_MESSAGE, "some error, connect administrator"}),
                                            ?MODULE:loop(Socket, Client)
                                    end;
                                {ok, join_self} ->
                                    Player = Client#client.player,
                                    Player2 = Player#player {
                                                server_pid = Client#client.server_pid
                                               },
                                    Client2 = Client#client {
                                                player = Player2
                                               },
                                    case mnesia:transaction( fun() -> mnesia:write(Player2) end) of
                                        {atomic, ok} ->
                                            ok = ?tcpsend(Socket, {?PP_JOINSERVER}),
                                            ?MODULE:loop(Socket, Client2);
                                        Other->
                                            io:fomrat("server loop other:~p~p: ~p~n", [?MODULE, ?LINE, Other]),
                                            ok = ?tcpsend(Socket, {?ERROR_MESSAGE, "some error, connect administrator"}),
                                            ?MODULE:loop(Socket, Client2)
                                    end;
                                {error, Msg} ->
                                    io:format("server loop error: ~w: ~w: ~w :  ~n", [Msg, ?MODULE, ?LINE]),
                                    ok = ?tcpsend(Socket, {?ERROR_MESSAGE, Msg}),
                                    ?MODULE:loop(Socket, Client)
                            end;
                        Pid ->
                            case Client#client.server_name of
                                ServerName ->
                                    ?MODULE:loop(Socket, Client);
                                _ ->
                                    io:format("server loop error: ~p not in server ~p ~n", [Client#client.player, ServerName]),
                                    ok = ?tcpsend(Socket, {?ERROR_MESSAGE, "you are not in this server"}),
                                    ?MODULE:loop(Socket, Client)
                            end
                    end;
                Other ->
                    io:format("receive otherClient=~w:~w~n",[Client, Other]),
                    ?MODULE:loop(Socket, Client)
            end;
       

首先进行合格行检查,如果已经登录进了服务器并且要登录进入的服务器和自己当前的服务器名字不一样,明显有问题么,告诉客户端,你丫不在我这儿,就别来骚扰我。如果还没有登录进服务器,就像serverstate请求,我要连接某个名字的服务器,你丫有话好好说,放我进去。如果serverstate返回了reconnect消息,则告诉客户端:“乖,到这里吧,这里人少”,否则的话,就说:“你丫我欢迎”。serverstate的判断方法用下面的方法实现的:

       handle_call({player_join, Servername, Client, Socket, Self}, _From, State) ->
    Result = case db:search(qlc:q([ServerDat#server.socketpid || ServerDat <- mnesia:table(server), 
                                                                 ServerDat#server.name =:= Servername, 
                                                                 ServerDat#server.socketpid /= none])) of
                 {atomic, []} ->
                     {error, "server not running"};
                 {atomic, ServerDat} ->
                     [Server2|_] = qsort(list_server(ServerDat, State)),
                     case Server2#server.socketpid of
                         Socket ->
                             Server3 = Server2#server {
                                         curuser = Server2#server.curuser + 1
                                        },
                             ets:insert(State#state.serverstate, {Server2#server.socketpid, Server3}),
                             ServerState = state({name, Servername}, State),
                             send_event(State#state.eventhandle, [{state, [ServerState]}]),
                             router:call({send_to_players, qlc:q([Player#player.id || Player <- mnesia:table(player),
                                                                             Player#player.socket /= none,
                                                                             Player#player.socket /= Self,
                                                                             Player#player.server_pid =:= none]),{?PP_SERVERLIST,[ServerState]}}),
                             {ok, join_self};
                         _ ->
                             Code = erlang:phash2(Client#player.nick ++ float_to_list(random:uniform()), 1 bsl 32),
                             {ok, {reconnect, {Server2#server.ip, Server2#server.port, Code}}}
                     end
             end,
    {reply, Result, State};
       

首先serverstate会查找,看服务器是否运行,如果运行的话,在所有的服务器中查找一个当前用户最少的,然后判断这个用户最少的服务器进程是否和当前用户的服务器进程一样,如果一样的话,则直接让用户进入,否则的话,就给出一个ip,port和code值让用户连接,这些在上面已经讨论了。

当客户端接收到重新连接服务器的时候,在新的ip和端口上建立新的连接,然后把code值发给服务器,告诉它:“你大爷的我刚才付过茶钱了。”服务器执行下面的检查程序,来进行用户的重新连接处理:

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据