码迷,mamicode.com
首页 > 其他好文 > 详细

【FOL】第九周

时间:2016-08-12 21:31:49      阅读:205      评论:0      收藏:0      [点我收藏+]

标签:

不知不觉又是三周过去了。

这几周忙了一下,其他时间全都在搞服务端,简直是酸爽的不行。。。不过还好出了些成果。

目前服务端有:

1、版本服务:游戏版本更新

2、账号服务:用户身份验证,返回各种连接(代理服务、聊天服务)

3、代理服务:获取游服列表、获取游服状态(是否需要排队)、进入游戏的验证、游服数据转发

4、队列服务:处理排队队列中用户的队列情况变化,并广播(本来这个是放在代理服务器上做的,但是我觉得广播起来有点恶心就分出来了,看起来各个服务的功能也清晰些)

5、游戏服务:游戏业务逻辑处理(作为1-n个特殊的客户端连接到代理服务器)

6、聊天服务

客户端方面,优化了一些网络通讯方面的代码,把各种消息重新整理了一遍。界面表现方面几乎没动过。

整个框架基本上实现了登录、选服、排队(等待、结束)、进入游戏、聊天。

 

想了一下,还是放段代码。

unit gate.handler;

interface

uses
  System.SysUtils, System.Classes, System.Math, diocp_coder_tcpServer,
  diocp_tcp_server, fol.msgcode, fol.types, fol.simpleMsgPack,
  fol.server.types, fol.server.session, gate.session, gate.cache;

procedure pushMsgData(pvMsgData: TSimpleMsgPack; pvContext: TIocpClientContext);
procedure execHeart(pvMsgData: TSimpleMsgPack; pvContext: TIOCPCoderClientContext);
procedure execOffline(pvContext: TIOCPCoderClientContext);

function execRequest(pvMsgData: TSimpleMsgPack; pvContext: TIOCPCoderClientContext): Integer;
function execRegister(pvMsgData: TSimpleMsgPack; pvContext: TIOCPCoderClientContext): Integer;
function execRegisterGameServiceClient(pvMsgData: TSimpleMsgPack; pvContext: TIOCPCoderClientContext): string;
function execRequestServerList(pvMsgData: TSimpleMsgPack): Integer;
function execRequestServerState(const pvServerID: Integer; pvMsgData: TSimpleMsgPack): Integer;
function execRequestStartGame(const pvServerID,pvUserID: Integer;
  pvMsgData: TSimpleMsgPack; pvContext: TIOCPCoderClientContext): Integer;
function execRequestGameService(pvMsgData: TSimpleMsgPack): Integer;
function execTranspond(pvMsgData: TSimpleMsgPack; pvContext: TIOCPCoderClientContext): Integer;

implementation

uses utils_safeLogger;

procedure pushMsgData(pvMsgData: TSimpleMsgPack; pvContext: TIocpClientContext);
var
  lvStream: TMemoryStream;
begin
  lvStream:= TMemoryStream.Create;
  try
    if Assigned(pvContext) then
    begin
      pvMsgData.Add(result,MSG_RESULT_Success);
      pvMsgData.EncodeToStream(lvStream);
      lvStream.Position:= 0;
      TIOCPCoderClientContext(pvContext).WriteObject(lvStream);
    end;
  finally
    lvStream.Free;
  end;
end;

procedure execHeart(pvMsgData: TSimpleMsgPack; pvContext: TIOCPCoderClientContext);
begin
  if pvContext.LockContext(keeplive, nil) then
  try
    gvSessionManager.validChecked(pvContext);
    pvMsgData.Clear;
  finally
    pvContext.UnLockContext(keeplive, nil);
  end;
end;

procedure execOffline(pvContext: TIOCPCoderClientContext);
var
  lvServerID: Integer;
  lvUserID, lvServerKey: string;
begin
  if pvContext.Data <> nil then
  begin
    {
       1. 游戏客户端: 只是连接了代理服务器,并未选服登录游戏 (断开不需要处理)
       2. 游戏客户端: 已经进入游戏的,断开需要更新对应服务器freenum
       3. OM工具: 断开不需要处理
       4. 游戏服务: 断开需要把游服记录删除(或者更新state)
    }
    lvServerID:= TClientSession(pvContext.Data).ServerID;
    lvUserID:= TClientSession(pvContext.Data).SessionID;
    case TClientSession(pvContext.Data).ClientType of
      tfctGameClient:
        begin
          sfLogger.logMessage([INFO]: Client offline, serverid=+inttostr(lvServerID));
          if lvServerID = 0 then exit;
          //更新freenum(freenum+1)
          sfLogger.logMessage([INFO]: Client offline, userid=+lvUserID);
          lvServerKey:= Format(server:%.3d,[lvServerID]);
          redisClient.HINCRBY(lvServerKey,freenum,1);
          //kickOut这个session(或者设置为无效session)
          gvSessionManager.kickOutGameClient(lvUserID);
        end;
      tfctGameServiceClient:
        begin
          //更新游服列表
          lvServerKey:= Format(server:%.3d,[StrToInt(lvUserID)]);
          redisClient.DEL([lvServerKey]);
          gvSessionManager.kickOutGameService(lvUserID);
        end;
      tfctOMClient:
        begin
          sfLogger.logMessage([INFO]: OMClient offline);
          gvSessionManager.kickOutOMClient(lvUserID);
        end;
    end;
  end;
end;

function execRegister(pvMsgData: TSimpleMsgPack; pvContext: TIOCPCoderClientContext): Integer;
var
  lvClientType: Integer;
  lvSessionID: string;
begin
  if pvContext.LockContext(register, nil) then
  try
    lvClientType:= pvMsgData.I[client_type];
    case lvClientType of
      ord(tfctGameClient):
        lvSessionID:= gvSessionManager.takeAGameClientSession(pvContext, pvMsgData.S[client_id]);
      ord(tfctGameServiceClient):
        lvSessionID:= execRegisterGameServiceClient(pvMsgData, pvContext);
      ord(tfctOMClient):
        lvSessionID:= gvSessionManager.takeAOMClientSession(pvContext, pvMsgData.S[client_id]);
    end;
    pvMsgData.Clear;
    pvMsgData.S[token]:= (gate)token_+lvSessionID;
    result:= MSG_RESULT_Success;
  finally
    pvContext.UnLockContext(register, nil);
  end;
end;

function execRegisterGameServiceClient(pvMsgData: TSimpleMsgPack; pvContext: TIOCPCoderClientContext): string;
var
  lvServiceID, lvServiceName, lvServerKey, lvMaxConn: string;
begin
  lvServiceID:= pvMsgData.S[client_id];
  lvServiceName:= pvMsgData.S[client_name];
  lvMaxConn:= pvMsgData.S[client_maxconn];
  result:= gvSessionManager.takeAGameServiceSession(pvContext,lvServiceID);

  //example: hmset server:001 name 五行之始 state 1 freenum 1000
  lvServerKey:= Format(server:%.3d,[StrToInt(lvServiceID)]);
  redisClient.HMSET(lvServerKey,[name,state,freenum],[lvServiceName,0,lvMaxConn]);
end;

function execRequest(pvMsgData: TSimpleMsgPack; pvContext: TIOCPCoderClientContext): Integer;
var
  lvMsgcode, lvCallbackID, lvServerID, lvUserID: Integer;
begin
  lvMsgcode:= pvMsgData.I[msg_code];
  lvCallbackID:= pvMsgData.I[callbackid];
  sfLogger.logMessage([INFO]: Receive a message package, msgcode= + inttostr(lvMsgcode));
  case lvMsgcode of
    MSG_NET_Register: result:= execRegister(pvMsgData, pvContext);
    MSG_NET_GetServerList:
      begin
        pvMsgData.Clear;
        result:= execRequestServerList(pvMsgData);
      end;
    MSG_NET_GetServerState:
      begin
        lvServerID:= pvMsgData.I[serverid];
        pvMsgData.Clear;
        result:= execRequestServerState(lvServerID,pvMsgData);
      end;
    MSG_NET_StartGame:
      begin
        lvServerID:= pvMsgData.I[serverid];
        lvUserID:= pvMsgData.I[userid];
        pvMsgData.Clear;
        result:= execRequestStartGame(lvServerID,lvUserID,pvMsgData,pvContext);
      end;
    else
      begin
        execRequestGameService(pvMsgData);
        pvMsgData.Clear;
        exit;
      end;
  end;
  pvMsgData.Add(callbackid, lvCallbackID);
end;

function execRequestServerList(pvMsgData: TSimpleMsgPack): Integer;
var
  i: Integer;
  lvServerKey: string;
  lvData: TArray<string>;
begin
  for i:= 1 to 999 do
  begin
    lvServerKey:= Format(server:%.3d,[i]);
    lvData:= redisClient.HMGET(lvServerKey, [name, state]);
    if (Length(lvData)=0) or (lvData[0]=‘‘) then break;
    pvMsgData.Add(lvData[0], StrToInt(lvData[1]));
  end;
  result:= MSG_RESULT_Success;
end;

function execRequestServerState(const pvServerID: Integer; pvMsgData: TSimpleMsgPack): Integer;
var
  lvServerKey: string;
  lvFreeNum: Integer;
begin
  lvServerKey:= Format(server:%.3d,[pvServerID]);
  redisClient.HGET(lvServerKey,freenum,lvFreeNum);
  case lvFreeNum of
    0: result:= MSG_RESULT_Queue;
   -1: raise exception.Create(invalid freenum.);
    else result:= MSG_RESULT_Success;
  end;
end;

function execRequestStartGame(const pvServerID,pvUserID: Integer;
  pvMsgData: TSimpleMsgPack; pvContext: TIOCPCoderClientContext): Integer;
var
  lvServerKey, lvQueueKey: string;
  lvFreeNum, lvState: Integer;
begin
  if pvContext.Data <> nil then
  begin
    lvServerKey:= Format(server:%.3d,[pvServerID]);
    redisClient.HGET(lvServerKey,state,lvState);
    if lvState <> 0 then raise Exception.Create(Service is Closed.);
    redisClient.HGET(lvServerKey,freenum,lvFreeNum);
    if lvFreeNum <= 0 then raise Exception.Create(Invalid request, free num is zero.);
    //
    TClientSession(pvContext.Data).ServerID:= pvServerID;
    TClientSession(pvContext.Data).State:= tusOnline;
    //更新freenum(freenum-1)
    lvFreeNum:= Max(lvFreeNum - 1,0);
    redisClient.HSET(lvServerKey,freenum,lvFreeNum);
    //广播上线消息给好友
  end;
  result:= MSG_RESULT_Success;
end;

function execRequestGameService(pvMsgData: TSimpleMsgPack): Integer;
var
  lvServerID: string;
  lvContext: TIocpClientContext;
begin
  lvServerID:= IntToStr(pvMsgData.I[serverid]);
  lvContext:= gvSessionManager.findGameServiceContext(lvServerID);
  pushMsgData(pvMsgData,lvContext);
end;

function execTranspond(pvMsgData: TSimpleMsgPack; pvContext: TIOCPCoderClientContext): Integer;
var
  lvUserID: string;
  lvContext: TIocpClientContext;
begin
  lvUserID:= pvMsgData.S[userid];
  lvContext:= gvSessionManager.findGameClientContext(lvUserID);
  pushMsgData(pvMsgData,lvContext);
end;

end.

 

【FOL】第九周

标签:

原文地址:http://www.cnblogs.com/crymm/p/5766579.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!