服务器消息制作
在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
|