游戏开发论坛

 找回密码
 立即注册
搜索
查看: 2282|回复: 0

Unity结合C++开发服务器实现多人游戏(四)

[复制链接]

29

主题

38

帖子

384

积分

中级会员

Rank: 3Rank: 3

积分
384
QQ
发表于 2017-2-21 11:51:21 | 显示全部楼层 |阅读模式
服务器消息制作

在ProudNet接收信息时可以使用多种方法,其中之一是使用RMI.
因为通过RMI接收信息由机器代码进行自动转换,所以在程序开发中可以避免不必要的失误。
在服务器端添加一个新的PIDL文件,PIDL文件使用Visual Studio Addon会很方便.
详细可参考:PIDL-addon 编译器.
PIDL文件以接收信息函数形式表现,此函数可进行直接调用.
PIDL 文件中生成proxy和 stub代码. Proxy代表信息发送stub代表信息接收.
Proxy的函数调用时,输入至少一个以上"运行此函数设备的HostID", 包含此函数的其它设备在 stub中运行. 以远程调用的形式接收消息.
新的PIDL文件Simple.PIDL添加至运行的程序中. 服务器与客户端共同使用的类库添加到项目或者添加到服务器项目.
rename cs(std::wstring, System.String);

global Simple 1000
{
    RequestLogin([in] std::wstring id, [in] std::wstring password);

    NotifyLoginSuccess();
    NotifyLoginFailed([in] std::wstring reason);
}
第一行rename的意思是, "C#中std::wstring可以替换为System.String".
RequestLogin, NotifyLoginSuccess, NotifyLoginFailed分别指的是 "与服务器的连接邀请" "与服务器连接成功" "与服务器连接失败".
进行编译后生成Simple.Proxy, Simple.Stub类. 创建对象实例包含了服务器和客户端.
Proxy为成员变数. Stub直接继承服务器类.
class SimpleServer
    :public Simple::Stub
{
public:
    Simple:: Proxy m_proxy;
在NetServer.Start运行之前, proxy和 stub对象添加到 NetServer.
m_netServer->AttachProxy(&m_proxy);
m_netServer->AttachStub(this);
客户端也添加proxy和 stub.并且添加到NetManager.cs.
Simple.Proxy m_proxy = new Simple.Proxy();
Simple.Stub m_stub = new Simple.Stub();
在调用NetClient.Connect之前 proxy, stub添加到 NetClient对象.
m_netClient.AttachProxy(m_proxy);
m_netClient.AttachStub(m_stub);
客户端连接服务器成功的话, 可直接调用远程函数RequestLogin.
m_netClient.JoinServerCompleteHandler =
    (ErrorInfo info, ByteArray replyFromServer) =>
{
    if (info.errorType == ErrorType.ErrorType_Ok)
    {
        m_proxy.RequestLogin(HostID.HostID_Server,
            RmiContext.SecureReliableSend, m_userID, m_password); // (1)
        m_state = MyState.Connecting;
(1)代表的意义如下.
§  向服务器发送信息.
§  加密后发送.
§  发送输入的userID和 password.
服务器接收RequestLogin并处理. PIDL编译结果包含远程函数声明和构建C macro.
class SimpleServer
{
    DECRMI_Simple_RequestLogin;
然后添加进行处理的函数RequestLogin.
DEFRMI_Simple_RequestLogin(SimpleServer)
{
    cout << "RequestLogin " << StringT2A(id.c_str()) << " "
        << StringT2A(password.c_str()) << endl;
    // success!
    m_proxy.NotifyLoginSuccess(remote, RmiContext::ReliableSend);
    return true;
}
ProudNet的远程函数即,RMI函数需要一直是return true.
分析以上函数代码, 存在变量remote, id, password.
id,password是PIDL中所定义的, remote是 "远程函数调用,信息发送设备的HostID.
首先, 假设以上函数"一定登陆成功
在服务器中发送了NotifyLoginSuccess,客户端添加进行可处理的代码.
m_stub.NotifyLoginSuccess = (HostID remote, RmiContext rmiContext) =>
{
    m_state = MyState.Connected;

    return true;
};
m_stub.NotifyLoginFailed = (HostID remote, RmiContext rmiContext, System.String reason) =>
{
    Debug.Log(reason);
    m_disconnectNow = true;
    return true;
};
对以上代码进行说明
§  "登陆成功" 接收远程函数调用后, 转换为MyState.Connected同时隐藏登录窗口.
§  接收"登陆失败"后,输出失败的理由并断开连接.
注意:Client.Disconnect在 RMI事件处理函数中无法被调用.
使用以上变数或者其它方法调用Disconnect函数.
class NetManager
{
    void Update()
    {
        if (m_disconnectNow)
        {
            m_netClient.Disconnect();
            m_state = MyState.Disconnected;
            m_disconnectNow = false;
        }
现在,运行客户端和服务器点击Connect键. 客户端的GUI消失的话,代表服务器输出 RequestLogin,连接成功.
在此我们只使用远程函数变量int, string的基本类型,也可根据大家定义的构造体或者array进行接收.
详细请参考:PIDL的数据类型及Marshaling

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-2-25 00:01

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表