Разработка клиентов с использованием дескрипторов контекста
Единственное использование клиентской программы для дескриптора контекста — передавать его серверу каждый раз, когда клиент выполняет удаленный вызов процедуры. Клиентскому приложению не требуется доступ к содержимому дескриптора. Он не должен пытаться каким-либо образом изменить контекст обработки данных. Удаленные процедуры, вызываемые клиентом, выполняют все необходимые операции в контексте сервера.
Перед запросом дескриптора контекста с сервера клиенты должны установить привязку с сервером. Клиент может использовать автоматический, неявный или явный дескриптор привязки. Используя допустимый дескриптор привязки, клиент может вызвать удаленную процедуру на сервере, которая возвращает открытый (не null) дескриптор контекста или передает его через параметр [out] в списке параметров удаленной процедуры.
Клиенты могут использовать открытые дескрипторы контекста любым способом. Однако они должны сделать дескриптор недействительным, когда он им больше не нужен. Это можно сделать двумя способами:
- Для вызова удаленной процедуры, предлагаемой серверной программой, которая освобождает контекст и закрывает дескриптор контекста (устанавливает для него значение NULL).
- Если сервер недоступен, вызовите функцию RpcSsDeтяжелемClientContext .
Второй подход очищает только состояние на стороне клиента и не очищает состояние на стороне сервера, поэтому его следует использовать только при подозрении на сетевую секцию, а клиент и сервер будут выполнять независимую очистку. Сервер выполняет независимую очистку с помощью подпрограммы запуска, клиент делает это с помощью функции RpcSsDegradClientContext .
В следующем фрагменте кода представлен пример того, как клиент может использовать дескриптор контекста. Чтобы просмотреть определение интерфейса, используемого в этом примере, см. раздел Разработка интерфейса с использованием дескрипторов контекста. Сведения о реализации сервера см. в разделе Разработка сервера с использованием дескрипторов контекста.
В этом примере клиент вызывает 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);
}