2009-11-22 68 views
4

我想在DataSnap服務器/客戶端之間傳輸一些大流(〜1Mb)但無濟於事。我試圖瞭解吉姆蒂爾尼(http://blogs.embarcadero.com/jimtierney/2009/04/06/31461)的代碼,但沒有運氣,我甚至無法編譯代碼,因爲缺少一個庫,無論如何...與DataSnap的大流

流的最大尺寸我能收到的是64k,所以任何提示/想法/代碼示例你可以提供一個週末程序員像我一樣會很受歡迎。謝謝!

我的服務器代碼:

function TsrvMethods.getStream(iCount: integer): TStream; 
begin 
    Result := dummyStream('', iCount); 
end; 

function dummyStream(sCnt: string; iCount: integer): TStream; 
begin 
    Result := TMemoryStream.Create; 
    while iCount > 1 do begin 
    Result.Write(Pointer(sCnt)^, Length(sCnt)); 
    Dec(iCount); 
    end; 
    Result.Seek(0, TSeekOrigin.soBeginning); 
end; 

我的客戶端調用代碼:

procedure TfrmMain.butStreamClick(Sender: TObject); 
var 
    sStr : TStream; 
begin 
    cycleConnection; //make sure we have an active connection 

    with TsrvMethodsClient.Create(SQLConn.DBXConnection, False) do begin 
    sStr := getStream(Integer(SpinCount.Value)); 
    Free; 
    end; 
    FreeAndNil(sStr); 
end; 
+0

這段代碼有什麼問題?請讓我們知道編譯時間或運行時錯誤是什麼以及在什麼行上。 – 2009-11-22 18:06:39

+0

我發佈的代碼適用於小於64k的流。當發送更大的流時,沒有錯誤,但流的另一端是空的(或不發送/接收)。 – 2009-11-22 19:06:07

回答

6

其實,我覺得i`ve得到它。我發佈這個答案也許有人需要這個。

procedure TfrmMain.butStreamClick(Sender: TObject); 
const 
    iBufSize = 128; 
var 
    sStr : TStream; 
    sMem : TMemoryStream; 
    buf: PByte; 
    iRead: integer; 
begin 
    cycleConnection; 

    with TsrvMethodsClient.Create(SQLConn.DBXConnection, False) do begin 

    sStr := getStream(500000); //500k stream 

    GetMem(buf, iBufSize); 
    sMem := TMemoryStream.Create; 
    try 
     repeat 
     iRead := sStr.Read(Pointer(buf)^, iBufSize); 

     if iRead > 0 then sMem.WriteBuffer(Pointer(buf)^, iRead); 
     if iRead < iBufSize then break; 
     until iRead < iBufSize; 
    finally 
     FreeMem(buf, iBufSize); 
    end; 

    Free; 
    end; 
    FreeAndNil(sStr); 
    FreeAndNil(sMem); 
end; 

P.S.

通過DataSnap代碼示例進行搜索我發現一個(速度相關的)改進是將iBufSize設置爲61440(或等效的十六進制值$ F000),這似乎是一次可以接收的最大尺寸。如果接收流較大,則報告的大小將爲-1,並且需要上述代碼才能讀取整個流。