问题描述
我正在尝试编写一个 RPC 服务器应用程序和一个 RPC 客户端应用程序,以便来回发送消息。
按照本教程,我可以成功地从客户端向服务器发送消息:https://www.codeproject.com/Articles/4837/Introduction-to-RPC-Part-1。现在修改了代码,以便服务器也可以将响应发送回客户端。
这是我的 IDL 文件:
import "oaidl.idl";
import "ocidl.idl";
[
// A unique identifier that distinguishes this
// interface from other interfaces.
uuid(00000001-EAF3-4A7A-A0F2-BCE4C30DA77E),// This is version 1.0 of this interface.
version(1.0),// This interface will use an implicit binding
// handle named hExample1Binding.
implicit_handle(handle_t hExample1Binding)
]
interface Example1 // The interface is named Example1
{
// A function that takes a zero-terminated string.
void Output(
[in,string] const char* szInput,[out,string,size_is(500)] const char* szOutput);
}
这是我的服务器代码:
// PlainRPCServer.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
// File ContextExampleServer.cpp
#include <string>
#include <iostream>
#include "Example1_h.h"
using namespace std;
// Server function.
void Output(
/* [string][in] */ const unsigned char *szInput,/* [size_is][string][out] */ const unsigned char *szOutput)
{
std::cout << "from client " << szInput << std::endl;
szOutput = "Reply from the server";
return;
}
// Naive security callback.
RPC_STATUS CALLBACK SecurityCallback(RPC_IF_HANDLE /*hInterface*/,void* /*pBindingHandle*/)
{
return RPC_S_OK; // Always allow anyone.
}
int main()
{
RPC_STATUS status;
// Uses the protocol combined with the endpoint for receiving
// remote procedure calls.
status = RpcServerUseProtseqEpA(
(RPC_CSTR)("ncacn_ip_tcp"),// Use TCP/IP protocol.
RPC_C_PROTSEQ_MAX_REQS_DEFAULT,// Backlog queue length for TCP/IP.
(RPC_CSTR)("4747"),// TCP/IP port to use.
NULL); // No security.
if (status)
exit(status);
// Registers the Example1 interface.
status = RpcServerRegisterIf2(
Example1_v1_0_s_ifspec,// Interface to register.
NULL,// Use the MIDL generated entry-point vector.
NULL,// Use the MIDL generated entry-point vector.
RPC_IF_ALLOW_CALLBACKS_WITH_NO_AUTH,// Forces use of security callback.
RPC_C_LISTEN_MAX_CALLS_DEFAULT,// Use default number of concurrent calls.
(unsigned)-1,// Infinite max size of incoming data blocks.
SecurityCallback); // Naive security callback.
if (status)
exit(status);
// Start to listen for remote procedure
// calls for all registered interfaces.
// This call will not return until
// RpcMgmtStopServerListening is called.
status = RpcServerListen(
1,// Recommended minimum number of threads.
RPC_C_LISTEN_MAX_CALLS_DEFAULT,// Recommended maximum number of threads.
FALSE); // Start listening Now.
if (status)
exit(status);
}
// Memory allocation function for RPC.
// The runtime uses these two functions for allocating/deallocating
// enough memory to pass the string to the server.
void* __RPC_USER midl_user_allocate(size_t size)
{
return malloc(size);
}
// Memory deallocation function for RPC.
void __RPC_USER midl_user_free(void* p)
{
free(p);
}
服务器正在使用此代码运行。但是,由于客户端不工作,我不确定服务器是否正常工作。
这是我客户的代码:
// PlainRPcclient.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include "Example1_h.h"
using namespace std;
int main()
{
RPC_STATUS status;
RPC_CSTR szStringBinding = NULL;
// Creates a string binding handle.
// This function is nothing more than a printf.
// Connection is not done here.
status = RpcStringBindingComposeA(
NULL,// UUID to bind to.
(RPC_CSTR)("ncacn_ip_tcp"),// Use TCP/IP protocol.
(RPC_CSTR)("localhost"),// TCP/IP network address to use.
(RPC_CSTR)("4747"),// TCP/IP port to use.
NULL,// Protocol dependent network options to use.
&szStringBinding); // String binding output.
if (status)
exit(status);
// Validates the format of the string binding handle and converts
// it to a binding handle.
// Connection is not done here either.
status = RpcBindingFromStringBindingA(
szStringBinding,// The string binding to validate.
&hExample1Binding); // Put the result in the implicit binding
// handle defined in the IDL file.
if (status)
exit(status);
RpcTryExcept
{
// Calls the RPC function. The hExample1Binding binding handle
// is used implicitly.
// Connection is done here.
const unsigned char* serverMsg = NULL;
Output((const unsigned char *)"msg from the client",serverMsg);
}
RpcExcept(1)
{
std::cerr << "Runtime reported exception " << RpcExceptionCode()
<< std::endl;
}
RpcEndExcept
// Free the memory allocated by a string.
status = RpcStringFreeA(
&szStringBinding); // String to be freed.
if (status)
exit(status);
// Releases binding handle resources and disconnects from the server.
status = RpcBindingFree(
&hExample1Binding); // Frees the implicit binding handle defined in the IDL file.
if (status)
exit(status);
}
// Memory allocation function for RPC.
// The runtime uses these two functions for allocating/deallocating
// enough memory to pass the string to the server.
void* __RPC_USER midl_user_allocate(size_t size)
{
return malloc(size);
}
// Memory deallocation function for RPC.
void __RPC_USER midl_user_free(void* p)
{
free(p);
}
我的客户端代码终止于:运行时报告异常 1780
注意:我使用的是 VS2015(以防万一)。
我的问题:
- 从客户端调用远程方法“输出”有问题,但我想不通。 serverMsg = NULL 的原因可以在 https://docs.microsoft.com/en-us/windows/win32/rpc/idl-techniques-for-better-interface-and-method-design 中找到(客户端应用程序组件在调用 RPC 方法时必须将 ppStr(对于我的代码是 serverMsg)设置为 NULL。)
- 如何将消息从服务器发送回客户端?我在 MSDN 中找不到这个例子。 (目前,我只是这样做:szOutput = "Reply from the server" 在服务器代码中)
- 以及如何在客户端应用程序中处理接收到的消息? (我的意思是如何分配消息并在客户端中使用它)?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)