Compartir a través de


Desarrollo de servidores mediante identificadores de contexto

Desde la perspectiva del desarrollo del programa de servidor, un identificador de contexto es un puntero sin tipo. Los programas de servidor inicializan los identificadores de contexto apuntando a datos en memoria o en alguna otra forma de almacenamiento (como archivos en discos).

Por ejemplo, supongamos que un cliente usa un identificador de contexto para solicitar una serie de actualizaciones a un registro de una base de datos. El cliente llama a un procedimiento remoto en el servidor y lo pasa una clave de búsqueda. El programa de servidor busca en la base de datos la clave de búsqueda y obtiene el número de registro entero del registro coincidente. A continuación, el servidor puede apuntar un puntero a void en una ubicación de memoria que contenga el número de registro. Cuando se devuelve, el procedimiento remoto tendría que devolver el puntero como identificador de contexto a través de su valor devuelto o su lista de parámetros. El cliente tendría que pasar el puntero al servidor cada vez que llamó a procedimientos remotos para actualizar el registro. Durante cada una de estas operaciones de actualización, el servidor convertiría el puntero void en un puntero a un entero.

Después de que el programa de servidor apunte el identificador de contexto en los datos de contexto, el identificador se considera abierto. Los identificadores que contienen un valor NULL se cierran. El servidor mantiene un identificador de contexto abierto hasta que el cliente llama a un procedimiento remoto que lo cierra. Si la sesión del cliente finaliza mientras el identificador está abierto, el tiempo de ejecución de RPC llama a la rutina de ejecución del servidor para liberar el identificador.

En el fragmento de código siguiente se muestra cómo un servidor puede implementar un identificador de contexto. En este ejemplo, el servidor mantiene un archivo de datos que el cliente escribe en mediante procedimientos remotos. La información de contexto es un identificador de archivo que realiza un seguimiento de la ubicación actual en el archivo donde el servidor escribirá datos. El identificador de archivo se empaqueta como identificador de contexto en la lista de parámetros para las llamadas a procedimientos remotos. Una estructura contiene el nombre de archivo y el identificador de archivo. La definición de interfaz de este ejemplo se muestra en Desarrollo de interfaz mediante identificadores de contexto.

/* cxhndlp.c (fragment of file containing remote procedures) */
typedef struct 
{
     FILE* hFile;
     char   achFile[256];
} FILE_CONTEXT_TYPE;

La función RemoteOpen abre un archivo en el servidor:

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);
    }
}

La función RemoteRead lee un archivo en el servidor.

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); 
}

La función RemoteClose cierra un archivo en el servidor. Tenga en cuenta que la aplicación de servidor tiene que asignar NULL al identificador de contexto como parte de la función close. Esto se comunica con el código auxiliar del servidor y la biblioteca en tiempo de ejecución rpc que se ha eliminado el identificador de contexto. De lo contrario, la conexión se mantendrá abierta y, finalmente, se producirá una reducción del contexto.

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;
}

Nota

Aunque se espera que el cliente pase un identificador de contexto válido a una llamada con atributos direccionales [in, out] , RPC no rechaza los identificadores de contexto NULL para esta combinación de atributos direccionales. El identificador de contexto NULL se pasa al servidor como puntero NULL . El código de servidor para las llamadas que contienen un identificador de contexto [in, out] debe escribirse para evitar una infracción de acceso cuando se recibe un puntero NULL .