Pengembangan Server Menggunakan Pegangan Konteks

Dari perspektif pengembangan program server, handle konteks adalah penunjuk tanpa tipe. Program server menginisialisasi handel konteks dengan mengarahkannya ke data dalam memori atau pada beberapa bentuk penyimpanan lain (seperti file pada disk).

Misalnya, klien menggunakan handel konteks untuk meminta serangkaian pembaruan pada rekaman dalam database. Pelanggan memanggil prosedur jarak jauh di server dan meneruskan kunci pencarian kepadanya. Program server mencari database untuk kunci pencarian dan mendapatkan nomor rekaman bilangan bulat dari rekaman yang cocok. Server kemudian dapat menunjukkan penunjuk tipe void ke lokasi memori yang berisi nomor catatan. Ketika kembali, prosedur jarak jauh harus mengembalikan penunjuk sebagai handel konteks melalui nilai pengembaliannya atau daftar parameternya. Klien harus meneruskan pointer ke server setiap kali memanggil prosedur remote untuk memperbarui catatan. Selama setiap operasi pembaruan ini, server akan mengonversi penunjuk void menjadi penunjuk ke bilangan bulat.

Setelah program server mengarahkan pegangan konteks ke data konteks, pegangan dianggap terbuka. Handel yang berisi nilai NULL ditutup. Server mempertahankan handle konteks yang telah dibuka sampai klien memanggil prosedur remote yang menutupnya. Jika sesi klien berakhir saat handle terbuka, waktu proses RPC memanggil rutinitas run-down server untuk membebaskan handle.

Fragmen kode berikut menunjukkan bagaimana server dapat menerapkan handel konteks. Dalam contoh ini, server mempertahankan file data yang ditulis klien dengan menggunakan prosedur jarak jauh. Informasi konteks adalah pegangan berkas yang memantau posisi saat ini dalam berkas dimana server akan menulis data. Pegangan berkas dipaketkan sebagai pegangan konteks dalam daftar parameter untuk panggilan prosedur jarak jauh. Struktur berisi nama file dan handle dari file. Definisi dari antarmuka dalam contoh ini ditampilkan dalam Pengembangan Antarmuka Menggunakan Handle Konteks.

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

Fungsi RemoteOpen membuka file di server:

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

Fungsi RemoteRead membaca file di server.

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

Fungsi RemoteClose menutup file di server. Perhatikan bahwa aplikasi server harus menetapkan NULL ke handle konteks sebagai bagian dari fungsi penutupan. Ini memberi tahu stub server dan pustaka run-time RPC bahwa handle konteks telah dihapus. Jika tidak, koneksi akan tetap terbuka dan akhirnya pengurangan konteks akan terjadi.

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

Meskipun diharapkan klien meneruskan handle konteks yang valid ke panggilan dengan atribut arah [masuk, keluar], RPC tidak menolak handle konteks NULL untuk kombinasi atribut arah ini. Handle konteks NULL diteruskan ke server sebagai penunjuk NULL. Kode server untuk panggilan yang mengandung handle konteks [in, out] harus ditulis untuk menghindari pelanggaran akses memori ketika pointer NULL diterima.