2017-07-22 12 views
1

TIdTCPServerからTIdTCPClientにデータを転送します。サーバー側では Indy TCP Server/Clientを使用してデータを転送する方法は?

は私が持っている:

procedure TForm1.IdTCPServer1Execute(AContext: TIdContext); 
var x:Integer; 
    Received:String; 
    SendBuff:TBytes; 
    hFile:THandle; 
    fSize:Int64; 
begin 
fSize:=0; 
if MOpenFileForRead(hFile,MGetExePath+'\test.jpg') then begin 
    fSize:=MFileSize(hFile); 
    SetLength(SendBuff,fSize); 
    MReadFile(hFile,SendBuff[0],fSize); 
    MCloseFile(hFile); 
end; 

// ... here the SendBuff contains valid data, I checked. 

repeat 
    Received:=AContext.Connection.Socket.ReadLn; 
    if not AContext.Connection.Connected then Exit; 
    if Received=CMD_TEST_FILE then begin 
    AContext.Connection.Socket.Write(fSize); 
    AContext.Connection.Socket.WriteBufferOpen; 
    AContext.Connection.Socket.Write(SendBuff); 
    AContext.Connection.Socket.WriteBufferClose; 
    end; 
until False; 
end; 

とクライアント側:

procedure TForm1.Button2Click(Sender: TObject); 
var fSize:Int64; 
    RecvBuff:TBytes; 
    hFile:THandle; 
begin 
    IdTCPClient1.Socket.WriteLn(CMD_TEST_FILE); 
    fSize:=IdTCPClient1.Socket.ReadInt64; 
    SetLength(RecvBuff,fSize); 
    IdTCPClient1.Socket.ReadBytes(RecvBuff,fSize); 
    if MCreateFile(hFile, MGetExePath+'\new.jpg') then begin 
    MWriteFile(hFile,RecvBuff[0],fSize); 
    MCloseFile(hFile); 
    end; 
    Memo1.Lines.Add('ok'); 
end; 

...しかし、それは働いていません。私は使用された読み込みと書き込みのデータ関数をチェックして、彼らは大丈夫です。サーバでは、バッファはOKに設定されています。ファイルサイズはクライアントではOKですが、クライアントでのバッファの内容はゼロにすぎません。

P.S:この方法でファイルをストリームなどで送信しません。

答えて

2

あなたがReadBytes()の署名を見れば、それはデフォルトでTrueですオプションAAppendのパラメータがあります。

procedure ReadBytes(var VBuffer: TIdBytes; AByteCount: Integer; AAppend: Boolean = True); virtual; 

は真、それがソケットからバイトを読み込み、既存の最後にそれらを追加しますバイト配列。配列をあらかじめ割り当てているので、最初のバイトは未定義で、ファイルバイトは未定義のバイトの後に続きます。

  1. ストップ事前割り当てバイト配列を、ReadBytes()はあなたのためにそれを割り当ててみましょう:

    は、この問題を解決するには、次のいずれかにする必要があります。

    procedure TForm1.Button2Click(Sender: TObject); 
    var 
        fSize: Int64; 
        RecvBuff: TBytes; 
        hFile: THandle; 
    begin 
        IdTCPClient1.Socket.WriteLn(CMD_TEST_FILE); 
        fSize := IdTCPClient1.Socket.ReadInt64; 
        // SetLength(RecvBuff,fSize); // <-- remove this line 
        IdTCPClient1.Socket.ReadBytes(RecvBuffer, fSize); 
        if MCreateFile(hFile, MGetExePath+'\new.jpg') then 
        begin 
        MWriteFile(haile, RecvBuff[0], fSize); 
        MCloseFile(hFile); 
        end; 
        Memo1.Lines.Add('ok'); 
    end; 
    
  2. 予め割り当てアレイが、バイトがそれに代わりアペンドの既存のアレイを埋めるように、FalseにAAppendを設定。

    procedure TForm1.Button2Click(Sender: TObject); 
    var 
        fSize: Int64; 
        RecvBuff: TBytes; 
        hFile: THandle; 
    begin 
        IdTCPClient1.Socket.WriteLn(CMD_TEST_FILE); 
        fSize := IdTCPClient1.Socket.ReadInt64; 
        SetLength(RecvBuff, fSize); 
        IdTCPClient1.Socket.ReadBytes(RecvBuff, fSize, False); 
        if MCreateFile(hFile, MGetExePath+'\new.jpg') then 
        begin 
        MWriteFile(haile, RecvBuff[0], fSize); 
        MCloseFile(hFile); 
        end; 
        Memo1.Lines.Add('ok'); 
    end; 
    

更新:言われていること、私は強く、あなたがしたくないと言ってもかかわらず、代わりにTStreamを使用することをお勧め。

procedure TForm1.IdTCPServer1Connect(AContext: TIdContext); 
begin 
    AContext.Data := TFileStream.Create(MGetExePath+'\test.jpg', fmOpenRead or fmShareDenyWrite); 
    AContext.Connection.IOHandler.LargeStream := True; 
end; 

TForm1.IdTCPServer1Execute(AContext: TIdContext); 
var 
    Received: String; 
begin 
    Received := AContext.Connection.IOHandler.ReadLn; 
    if Received = CMD_TEST_FILE then 
    begin 
    AContext.Connection.IOHandler.Write(TStream(AContext.Data), 0, True); 
    end; 
end; 

procedure TForm1.Button2Click(Sender: TObject); 
var 
    FileName: string; 
    Strm: TStream; 
begin 
    FileName := MGetExePath+'\new.jpg'; 
    Strm := TFileStream.Create(FileName, fmCreate); 
    try 
    try 
     IdTCPClient1.IOHandler.WriteLn 
(CMD_TEST_FILE); 
     IdTCPClient1.IOHandler.ReadStream(Strm, -1, False); 
    finally 
     Strm.Free; 
    end; 
    except 
    DeleteFile(FileName); 
    raise; 
    end; 
    Memo1.Lines.Add('ok'); 
end; 
:それは非常にあなたが使用することを選択した通信プロトコルを壊すことなく、コードやメモリ管理を簡素化します
関連する問題