使用上下文句柄进行客户端开发

客户端程序对上下文句柄的唯一用途是每次客户端进行远程过程调用时将其传递给服务器。 客户端应用程序不需要访问句柄的内容。 它不应尝试以任何方式更改上下文句柄数据。 客户端调用的远程过程对服务器的上下文执行所有必要的操作。

在从服务器请求上下文句柄之前,客户端必须与服务器建立绑定。 客户端可以使用自动、隐式或显式绑定句柄。 使用有效的绑定句柄,客户端可以在服务器上调用远程过程,该远程过程返回打开 (非 NULL) 上下文句柄,或通过远程过程参数列表中的 [out] 参数传递一个。

客户端可以按所需的任何方式使用打开的上下文句柄。 但是,当不再需要句柄时,他们应该使句柄失效。 有两种方法可以执行此操作:

  • 若要调用服务器程序提供的、释放上下文并关闭上下文句柄的远程过程, (将其设置为 NULL) 。
  • 当服务器无法访问时,请调用 RpcSsDestroyClientContext 函数。

第二种方法仅清理客户端状态,不清理服务器端状态,因此仅应在怀疑网络分区时使用,并且客户端和服务器将执行独立的清理。 服务器通过运行例程执行独立清理,客户端使用 RpcSsDestroyClientContext 函数执行此操作。

以下代码片段演示了客户端如何使用上下文句柄的示例。 若要查看此示例使用的接口的定义,请参阅 使用上下文句柄进行接口开发。 有关服务器实现,请参阅 使用上下文句柄的服务器开发

在此示例中,客户端调用 RemoteOpen 以获取包含有效数据的上下文句柄。 然后,客户端可以在远程过程调用中使用上下文句柄。 由于它不再需要绑定句柄,客户端可以释放用于创建上下文句柄的显式句柄:

// cxhndlc.c  (fragment of client side application)
printf("Calling the remote procedure RemoteOpen\n");
if (RemoteOpen(&phContext, pszFileName) < 0) 
{
    printf("Unable to open %s\n", pszFileName);
    Shutdown();
    exit(2);
}
 
// Now the context handle also manages the binding.
// The variable hBindingHandle is a valid binding handle.
status = RpcBindingFree(&hBindingHandle);
printf("RpcBindingFree returned 0x%x\n", status);
if (status) 
    exit(status);

此示例中的客户端应用程序使用名为 RemoteRead 的过程读取服务器上的数据文件,直到遇到文件结尾。 然后,它通过调用 RemoteClose 关闭文件。 上下文句柄在 RemoteRead 中显示为参数,RemoteClose 的函数为:

printf("Calling the remote procedure RemoteRead\n");
do 
{
    cbRead = 1024; // Using a 1K buffer
    RemoteRead(phContext, pbBuf, &cbRead);
    // cbRead contains the number of bytes actually read.
    for (int i = 0; i < cbRead; i++)
        putchar(*(pbBuf+i));
} while(cbRead);
 
printf("Calling the remote procedure RemoteClose\n");
if (RemoteClose(&phContext) < 0 ) 
{
    printf("Close failed on %s\n", pszFileName);
    exit(2);
}