在用戶端上實作輸入管道
使用輸入管道將資料從用戶端傳輸到伺服器時,您必須實作提取程式。 提取程式必須尋找要傳輸的數據、將數據讀入緩衝區,以及設定要傳送的項目數目。 當伺服器開始將數據提取到本身時,並非所有的數據都必須在緩衝區中。 提取程式可以累加填入緩衝區。
當沒有任何數據要傳送時,程式會將最後一個自變數設定為零。 傳送所有數據時,提取程式應該在傳回之前執行任何必要的清除。 如果是 [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 的指標。 提取程式會在每次傳輸數據時重複使用此緩衝區。 較複雜的用戶端程式在伺服器從用戶端提取數據時,可能需要分配新的緩衝區。
用戶端存根會呼叫提取程式。 此範例中的提取程式會使用狀態變數來追蹤全域數據源緩衝區中要讀取的下一個位置。 它會將數據從來源緩衝區讀取到管道緩衝區。 用戶端存根會將數據傳送至伺服器。 傳送所有數據後,提取程式會將緩衝區大小設定為零。 這會告訴伺服器停止提取數據。
相關主題