Разработка клиентов с использованием объектов управления контекстом
Единственное использование клиентской программы для дескриптора контекста заключается в том, чтобы передать его серверу каждый раз, когда клиент выполняет удаленный вызов процедуры. Клиентское приложение не требует доступа к содержимому дескриптора. Он не должен пытаться изменить контекст обработки данных каким-либо образом. Удаленные процедуры, вызываемые клиентом, выполняют все необходимые операции в контексте сервера.
Перед запросом дескриптора контекста с сервера клиенты должны установить привязку с сервером. Клиент может использовать автоматический, неявный или явный дескриптор привязки. С помощью допустимого дескриптора привязки клиент может вызывать удаленную процедуру на сервере, которая возвращает открытый (не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);
}