zoukankan      html  css  js  c++  java
  • 使用kendynet编写网关服务

    网游服务器大多提供了网关服务,用于作为用户和内部服务器组之间通信代理.网关服务一方面将用户消息从客户端分发到正确的内部服务器.

    另一方面将来自内部服务器的数据包转发给客户端.一般对于网关应用来说,压力最大的就是广播服务。一个用户的在游戏中产生的行为消息

    可能要广播给周数百个能看得见他的其它玩家.下面用kendynet编写一个简单的网关服务,当然这只是一个示例程序,它只是简单的把来自一

    连接的数据发往另一个连接.真实网络游戏中的网关服务要复杂得多.

    首先介绍一下基本设计,

    static msgdisp_t  disp_to_server;
    static msgdisp_t  disp_to_client;
    sock_ident        to_server;

    首先定义两个消息处理器,一个用户处理来自用的消息,一个用于处理来自内部服务器的消息.

    然后是一个sock_ident,用于表示与内部服务器的连接.

    接着在main函数中:

        asynnet_t asynet = asynnet_new(3);//3个poller,1个用于监听,1个用于处理客户端连接,1个用于处理服务器连接
        msgdisp_t  disp_to_server = new_msgdisp(asynet,
                                      to_server_connect,
                                      to_server_connected,
                                      NULL,
                                      to_server_process,
                                      NULL);
    
        msgdisp_t  disp_to_client = new_msgdisp(asynet,
                                      to_client_connect,
                                      NULL,
                                      NULL,
                                      to_client_process,
                                      NULL);
    
        thread_t service1 = create_thread(THREAD_JOINABLE);
        thread_t service2 = create_thread(THREAD_JOINABLE);
    
        to_client_ip = argv[1];
        to_client_port = atoi(argv[2]);
    
    
        to_server_ip = argv[3];
        to_server_port = atoi(argv[4]);
    
        thread_start_run(service1,service_toserver,(void*)disp_to_server);
        sleepms(1000);
        thread_start_run(service2,service_toclient,(void*)disp_to_client);

    先创建一个异步网络引擎,传入参数3,表示创建3个poller,其中第1个用于处理监听套接口,第2个用于处于与内部服务器

    的连接,第3个用户处理和客户端的连接.

    接着用不同的消息回调函数创建两个消息服务.

    最后创建两个单独的线程分别运行两个消息服务.

    接着再来看一下回调服务的处理:

    void to_server_connected(msgdisp_t disp,sock_ident sock,const char *ip,int32_t port,uint32_t err)
    {
        to_server = sock;
    }
    
    
    int32_t to_client_process(msgdisp_t disp,sock_ident sock,rpacket_t rpk)
    {
        if(!eq_sockident(sock,to_server)){
            //from cliet,send to server
            push_msg(disp_to_server,(msg_t)rpk);
        }else
        {
            //from server,send to client
            sock_ident client = read_from_rpacket(rpk);
            asyn_send(client,wpk_create_by_other((struct packet*)rpk));
        }
        return 1;
    }
    
    void to_client_connect(msgdisp_t disp,sock_ident sock,const char *ip,int32_t port)
    {
        //用第3个poller处理到客户端的连接
        disp->bind(disp,3,sock,1,3*1000,0);
    }
    
    
    int32_t to_server_process(msgdisp_t disp,sock_ident sock,rpacket_t rpk)
    {
        if(!eq_sockident(sock,to_server)){
            //from cliet,send to server
            asyn_send(to_server,wpk_create_by_other((struct packet*)rpk));
        }else{
            //from server,send to client
            push_msg(disp_to_client,(msg_t)rpk);
        }
        return 1;
    }
    
    void to_server_connect(msgdisp_t disp,sock_ident sock,const char *ip,int32_t port)
    {
        //用第二个poller处理到服务器的连接
        disp->bind(disp,2,sock,1,3*1000,0);
    }

    首先注意两个connect回调,对于server绑定到2号poller,对于client绑定到3号poller.

    然后再看两个process函数.对于client的process函数来说,如果发现发包的套接口不是to_server,就将数据包

    投递给disp_to_server,由disp_to_server将这个数据包发送给内部服务.如果发现数据包是来自to_server,

    那么就从数据包中读出发送目标,然后将数据包发送给目标客户端.

    server的process函数则正好相反,将来自to_server的消息投递给disp_to_client.将来自客户端的消息从to_server

    发送出去.一个简单的消息转发服务就这样实现了。

    完整的示例程序可以参看:

    https://github.com/sniperHW/luanet/blob/master/kendynet/test/gateservice.c

  • 相关阅读:
    Android学习笔记(四十):Preference的使用
    我的Android笔记(十一)——使用Preference保存设置
    Vim简明教程【CoolShell】
    普通人的编辑利器——Vim
    终端shell显示当前git分支_修订版
    代码规范须知_V1.0_20140703
    Android 4.4源码编译过程
    一个帖子学会Android开发四大组件
    什么是软件质量?
    软件配置管理的作用?软件配置包括什么?
  • 原文地址:https://www.cnblogs.com/sniperHW/p/3519379.html
Copyright © 2011-2022 走看看