共用方式為


在用戶端上實作輸入管道

使用輸入管道將資料從用戶端傳輸到伺服器時,您必須實作提取程式。 提取程式必須尋找要傳輸的資料、將資料讀取至緩衝區,以及設定要傳送的專案數目。 並非所有的資料在伺服器開始將資料提取至本身時,都必須在緩衝區中。 提取程式可以累加填滿緩衝區。

當沒有其他要傳送的資料時,程式會將最後一個引數設定為零。 傳送所有資料時,提取程式應該在傳回之前執行任何必要的清除。 對於為 [in, out] 管道的參數,提取程式必須在傳輸所有資料之後重設用戶端的狀態變數,讓推送程式可以使用它來接收資料。

下列範例會從 Platform Software Development Kit (SDK) 隨附的 Pipedemo 程式擷取。

//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

此範例包含 MIDL 編譯器所產生的標頭檔。 如需詳細資訊,請參閱 在 IDL 檔案中定義管道。 它也會宣告它用來作為 globalPipeData 資料來源的變數。 變數 globalBuffer 是提取程式用來傳送其從 globalPipeData 取得之資料區塊的緩衝區。

SendLongs 函式會宣告輸入管道,並配置資料來源變數 globalPipeData 的記憶體。 在您的用戶端/伺服器程式中,資料來源可以是用戶端所建立的檔案或結構。 您也可以讓用戶端程式從伺服器取得資料、處理它,並使用輸入管道將它傳回伺服器。 在此簡單範例中,資料來源是長整數的動態配置緩衝區。

在傳輸開始之前,用戶端必須設定狀態變數、提取程式及配置程式的指標。 這些指標會保留在用戶端宣告的管道變數中。 在此情況下,SendLongs 會宣告 inPipe。 您可以針對狀態變數使用任何適當的資料類型。

用戶端會叫用伺服器上的遠端程式,透過管道起始資料傳輸。 呼叫遠端程式會告知伺服器程式用戶端已準備好傳輸。 然後,伺服器可以將資料提取至本身。 此範例會叫用名為 InPipe 的遠端程式。 將資料傳送到伺服器之後,SendLongs 函式會釋放動態配置的緩衝區。

每次需要緩衝區時,不要配置記憶體。 此範例中的配置程式只會設定變數 globalBuffer 的指標。 每次傳輸資料時,提取程式都會重複使用此緩衝區。 當伺服器從用戶端提取資料時,可能需要配置更複雜的用戶端程式。

用戶端存根會呼叫提取程式。 此範例中的提取程式會使用狀態變數來追蹤要讀取之全域資料來源緩衝區中的下一個位置。 它會將資料從來源緩衝區讀取到管道緩衝區。 用戶端存根會將資料傳送至伺服器。 傳送所有資料後,提取程式會將緩衝區大小設定為零。 這會告訴伺服器停止提取資料。

/Oi