Bagikan melalui


Menerapkan Pipa Input pada Klien

Saat menggunakan pipa input untuk mentransfer data dari klien ke server, Anda harus menerapkan prosedur penarikan. Prosedur penarikan harus menemukan data yang akan ditransfer, membaca data ke dalam buffer, dan mengatur jumlah elemen yang akan dikirim. Tidak semua data harus berada di buffer ketika server mulai menarik data ke dirinya sendiri. Prosedur penarikan dapat mengisi buffer secara bertahap.

Ketika tidak ada lagi data untuk dikirim, prosedur mengatur argumen terakhirnya ke nol. Ketika semua data dikirim, prosedur penarikan harus melakukan pembersihan yang diperlukan sebelum kembali. Untuk parameter yang merupakan pipa [masuk, keluar], prosedur penarikan harus mengatur ulang variabel status klien setelah semua data ditransmisikan, sehingga prosedur pendorongan dapat menggunakannya untuk menerima data.

Contoh berikut diekstrak dari program Pipedemo yang disertakan dengan Kit Pengembangan Perangkat Lunak Platform (SDK).

//file: client.c (fragment)
#include <windows.h>
#include "pipedemo.h"
long *globalPipeData;
long    globalBuffer[BUF_SIZE];
 
ulong   pipeDataIndex; /* state variable */
 
void SendLongs()
{
    LONG_PIPE inPipe;
    int i;
    globalPipeData =
        (long *)malloc( sizeof(long) * PIPE_SIZE );
 
    for (i=0; i<PIPE_SIZE; i++)
        globalPipeData[i] = IN_VALUE;
 
    pipeDataIndex = 0;
    inPipe.state =  (rpc_ss_pipe_state_t )&pipeDataIndex;
    inPipe.pull  = PipePull;
    inPipe.alloc = PipeAlloc;
 
    InPipe( inPipe ); /* Make the rpc */
 
    free( (void *)globalPipeData );

}//end SendLongs
 
void PipeAlloc( rpc_ss_pipe_state_t stateInfo,
                ulong requestedSize,
                long **allocatedBuffer,
                ulong *allocatedSize )
{ 
    ulong *state = (ulong *)stateInfo;
    if ( requestedSize > (BUF_SIZE*sizeof(long)) )
    {
       *allocatedSize = BUF_SIZE * sizeof(long);
    }
    else
    {
       *allocatedSize = requestedSize;
    }
    *allocatedBuffer = globalBuffer; 
} //end PipeAlloc
 
void PipePull( rpc_ss_pipe_state_t stateInfo,
               long *inputBuffer,
               ulong maxBufSize,
               ulong *sizeToSend )
{
    ulong currentIndex;
    ulong i;
    ulong elementsToRead;
    ulong *state = (ulong *)stateInfo;

    currentIndex = *state;
    if (*state >=  PIPE_SIZE )
    {
        *sizeToSend = 0; /* end of pipe data */
        *state = 0; /* Reset the state = global index */
    }
    else 
    {
        if ( currentIndex + maxBufSize > PIPE_SIZE )
            elementsToRead = PIPE_SIZE - currentIndex;
        else
            elementsToRead = maxBufSize;
 
        for (i=0; i < elementsToRead; i++)
        {
            /*client sends data */
            inputBuffer[i] = globalPipeData[i + currentIndex];
        }
 
        *state +=   elementsToRead;
        *sizeToSend = elementsToRead;
    } 
}//end PipePull

Contoh ini mencakup file header yang dihasilkan oleh pengkompilasi MIDL. Untuk detailnya, lihat Menentukan Pipa dalam File IDL. Ini juga mendeklarasikan variabel yang digunakannya sebagai sumber data yang disebut globalPipeData. Variabel globalBuffer adalah buffer yang digunakan prosedur penarikan untuk mengirim blok data yang diperolehnya dari globalPipeData.

Fungsi SendLongs mendeklarasikan pipa input, dan mengalokasikan memori untuk variabel sumber data globalPipeData. Dalam program klien/server Anda, sumber data dapat menjadi file atau struktur yang dibuat klien. Anda juga dapat meminta program klien Anda mendapatkan data dari server, memprosesnya, dan mengembalikannya ke server menggunakan pipa input. Dalam contoh sederhana ini, sumber data adalah buffer bilangan bulat panjang yang dialokasikan secara dinamis.

Sebelum transfer dapat dimulai, klien harus mengatur penunjuk ke variabel status, prosedur penarikan, dan prosedur alokasi. Pointer ini disimpan dalam variabel pipa yang dinyatakan klien. Dalam hal ini, SendLongs menyatakan inPipe. Anda dapat menggunakan jenis data yang sesuai untuk variabel status Anda.

Klien memulai transfer data di seluruh pipa dengan memanggil prosedur jarak jauh di server. Memanggil prosedur jarak jauh memberi tahu program server bahwa klien siap untuk mengirimkan. Server kemudian dapat menarik data ke dirinya sendiri. Contoh ini memanggil prosedur jarak jauh yang disebut InPipe. Setelah data ditransfer ke server, fungsi SendLongs membebaskan buffer yang dialokasikan secara dinamis.

Daripada mengalokasikan memori setiap kali buffer diperlukan. prosedur alokasi dalam contoh ini hanya mengatur penunjuk ke variabel globalBuffer. Prosedur penarikan menggunakan kembali buffer ini setiap kali mentransfer data. Program klien yang lebih kompleks mungkin perlu mengalokasikan buffer baru setiap kali server menarik data dari klien.

Stub klien memanggil prosedur penarikan. Prosedur penarikan dalam contoh ini menggunakan variabel status untuk melacak posisi berikutnya di buffer sumber data global untuk dibaca. Ini membaca data dari buffer sumber ke dalam buffer pipa. Stub klien mengirimkan data ke server. Ketika semua data telah dikirim, prosedur penarikan mengatur ukuran buffer ke nol. Ini memberi tahu server untuk berhenti menarik data.

pipa

/Oi