Skip to content
ScutGame edited this page Jul 6, 2015 · 6 revisions

此章节介服务端与服务端之间如何通讯

概述

跟服务器打交道时,我们常常会碰到有N台后端服务器,它们之间又需要相互传递数据;

假设场景,有两台服务器A和B,A为游戏的业务服,B为游戏的战斗服务,A需要将玩家数据传给B要如何处理?

  • 首先需要确定服务器A和B支持的通讯协议是Http还是Socket,Http是短连接的不能支持双向通讯;

  • 确定由服务器A和B哪个做为服务的监听端,哪个做为客户端; 如果B可能会被多个服务依赖,则将B做为服务的监听端;

应用

这里设置服务器B为服务的监听端, 服务器A为客户端;

服务器B

打开服务器B的项目解决方案, 在Script/CsScript/Remote目录下新建立类Battle,并继承RemoteStruct类,代码如下:

namespace Game.Script.Remote
{

    public class Battle : RemoteStruct
    {
        private int _heroId;
        private int _combatNum;
        private int _gold;
        private List<int> _items = new List<int>();

        public Battle(ActionGetter paramGetter, MessageStructure response)
            : base(paramGetter, response)
        {
        }

        protected override bool Check()
        {
            if (paramGetter.GetInt("HeroId", ref _heroId) &&
               paramGetter.GetInt("CombatNum", ref _combatNum))
            {
                return true;
            }
            return false;
        }

        protected override void TakeRemote()
        {
            var session = paramGetter.GetSession();
            if (session == null)
            {
                ErrorCode = 10000;
                ErrorInfo = "Sessin is null.";
                return;
            }

            //Here to do something
            _gold = 100;
            _items.Add(1001);
        }

        protected override void BuildPacket()
        {
            //Send a reward here
            response.PushIntoStack(_gold);
            response.PushIntoStack(_items.Count);
            foreach (var itemId in _items)
            {
                var dsItem = new MessageStructure();
                dsItem.PushIntoStack(itemId);
                response.PushIntoStack(dsItem);
            }
        }
    }
}
  • Check方法:是接收客户端提交的参数信息较验,与Action的处理机制相同;
  • TakeRemote方法:处理请求,产生结果;
  • BuildPacket方法:将结果封包下发给客户端;

服务器A

服务器A做为客户端,需要发起请求,先选择服务器B使用哪种通讯;

Http请求

private RemoteService httpRemote;

private void Reuest()
{
    //创建一个代理类RemoteService的实例,参数:名称和 服务器B的地址
    httpRemote = RemoteService.CreateHttpProxy("proxy1", "http://127.0.0.1/service.aspx");
    //调用Battle处理,参数:“Battle”是上央服务器B定义的类
    var param = new RequestParam();
    param.Add("HeroId", 1001);
    param.Add("CombatNum", 100);
    httpRemote.Call("Battle", param, successCallback);
}

void successCallback(RemotePackage package)
{
    var reader = new MessageStructure(package.Message as byte[]);
    var gold = reader.ReadInt();
    var itemsCount = reader.ReadInt();
    var items = new int[itemsCount];
    for(int i = 0; i < itemsCount; i++)
    {
        reader.RecordStart();
        items[i] = reader.ReadInt();
        reader.RecordEnd();
    }
}

Socket请求

private RemoteService tcpRemote;

private void Reuest()
{
    //创建一个代理类RemoteService的实例,参数:名称,服务器B的地址与端口,心跳检测的间隔时间
    tcpRemote = RemoteService.CreateTcpProxy("proxy2", "127.0.0.1", 9001, 30 * 1000);
    //调用Battle处理,参数:“Battle”是上央服务器B定义的类
    var param = new RequestParam();
    param.Add("HeroId",1001);
    param.Add("CombatNum",100);
    tcpRemote.Call("Battle", param, successCallback);
}

void successCallback(RemotePackage package)
{
    var reader = new MessageStructure(package.Message as byte[]);
    var gold = reader.ReadInt();
    var itemsCount = reader.ReadInt();
    var items = new int[itemsCount];
    for(int i = 0; i < itemsCount; i++)
    {
        reader.RecordStart();
        items[i] = reader.ReadInt();
        reader.RecordEnd();
    }
}
Clone this wiki locally