Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
С точки зрения разработки программного обеспечения для серверов, дескриптор контекста является нетипизированным указателем. Серверные программы инициализируют контекстные обработчики, указывая их на данные в памяти или в другой форме хранения (например, файлы на дисках).
Например, предположим, что клиент использует дескриптор контекста для запроса ряда обновлений записи в базе данных. Клиент вызывает удаленную процедуру на сервере и передает его ключ поиска. Серверная программа выполняет поиск базы данных для ключа поиска и получает целочисленный номер записи сопоставления. Затем сервер может установить указатель типа void на область памяти, содержащую номер записи. Когда она вернется, удаленная процедура должна вернуть указатель в качестве дескриптора контекста через возвращаемое значение или через список параметров. Клиенту потребуется передать указатель на сервер при каждом вызове удаленных процедур для обновления записи. Во время каждой из этих операций обновления сервер преобразовывал бы указатель void в указатель на целое число.
После того как серверная программа указывает дескриптор контекста в контекстных данных, этот дескриптор считается открытым. Маркеры, содержащие значение null , закрыты. Сервер поддерживает открытый дескриптор контекста, пока клиент не вызовет удаленную процедуру, которая закрывает ее. Если сеанс клиента завершается, когда дескриптор открыт, среда выполнения RPC вызывает подпрограмму завершения сервера для освобождения дескриптора.
В следующем фрагменте кода показано, как сервер может реализовать дескриптор контекста. В этом примере сервер поддерживает файл данных, в который клиент записывает, используя удаленные процедуры. Сведения о контексте — это дескриптор файла, который отслеживает текущее расположение в файле, где сервер будет записывать данные. Дескриптор файла упаковывается как дескриптор контекста в списке параметров для удаленных вызовов процедур. Структура содержит имя файла и дескриптор файла. Определение интерфейса для этого примера показано в Разработка интерфейса с использованием дескрипторов контекста.
/* cxhndlp.c (fragment of file containing remote procedures) */
typedef struct
{
FILE* hFile;
char achFile[256];
} FILE_CONTEXT_TYPE;
Функция RemoteOpen открывает файл на сервере:
short RemoteOpen(
PPCONTEXT_HANDLE_TYPE pphContext,
unsigned char *pszFileName)
{
FILE *hFile;
FILE_CONTEXT_TYPE *pFileContext;
if ((hFile = fopen(pszFileName, "r")) == NULL)
{
*pphContext = (PCONTEXT_HANDLE_TYPE) NULL;
return(-1);
}
else
{
pFileContext = (FILE_CONTEXT_TYPE *)
MIDL_user_allocate(sizeof(FILE_CONTEXT_TYPE));
pFileContext->hFile = hFile;
// check if pszFileName is longer than 256 and if yes, return
// an error
strcpy_s(pFileContext->achFile, srlen(pszFileName), pszFileName);
*pphContext = (PCONTEXT_HANDLE_TYPE) pFileContext;
return(0);
}
}
Функция RemoteRead считывает файл на сервере.
short RemoteRead(
PCONTEXT_HANDLE_TYPE phContext,
unsigned char *pbBuf,
short *pcbBuf)
{
FILE_CONTEXT_TYPE *pFileContext;
printf("in RemoteRead\n");
pFileContext = (FILE_CONTEXT_TYPE *) phContext;
*pcbBuf = (short) fread(pbBuf, sizeof(char),
BUFSIZE,
pFileContext->hFile);
return(*pcbBuf);
}
Функция RemoteClose закрывает файл на сервере. Обратите внимание, что серверное приложение должно назначать NULL дескриптору контекста в рамках функции закрытия. Это сообщает заглушке сервера и библиотеке времени выполнения RPC о том, что дескриптор контекста был удален. В противном случае подключение будет оставаться открытым и в конечном итоге произойдет запуск контекста.
void RemoteClose(PPCONTEXT_HANDLE_TYPE pphContext)
{
FILE_CONTEXT_TYPE *pFileContext;
if (*pphContext == NULL)
{
//Log error, client tried to close a NULL handle.
return;
}
pFileContext = (FILE_CONTEXT_TYPE *)*pphContext;
printf("File %s closed.\n", pFileContext->achFile);
fclose(pFileConext->hFile);
MIDL_user_free(pFileContext);
// This tells the run-time, when it is marshalling the out
// parameters, that the context handle has been closed normally.
*pphContext = NULL;
}
Заметка
Хотя ожидается, что клиент передает допустимый дескриптор контекста вызову с атрибутами направления [in, out], RPC не отклоняет маркеры контекста NULL для этого сочетания атрибутов направления. Дескриптор контекста NULL передается серверу в виде указателя NULL. Код сервера для вызовов, содержащих дескриптор контекста [in, out], должен быть записан, чтобы избежать нарушения доступа при получении указателя на значение NULL NULL.