使用內容控制碼進行伺服器開發

從伺服器程式開發的觀點來看,內容控制碼是不具類型的指標。 伺服器程式會將內容控制碼指向記憶體中的資料或某種形式的儲存體 (,例如磁片上的檔案) 。

例如,假設用戶端使用內容控制碼來要求資料庫中記錄的一系列更新。 用戶端會在伺服器上呼叫遠端程式,並傳遞搜尋金鑰。 伺服器程式會搜尋資料庫中的搜尋索引鍵,並取得相符記錄的整數記錄號碼。 然後,伺服器就可以將指標指向包含記錄號碼的記憶體位置 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 給內容控制碼做為 close 函式的一部分。 這會與伺服器存根和已刪除內容控制碼的 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 指標時發生存取違規。