簡體   English   中英

使用TIdIOHandlerStream和TIdTCPClient讀取數據流

[英]Reading stream of Data using TIdIOHandlerStream and TIdTCPClient

我有一個需要使用TCP / IP連接到服務器的應用程序,然后僅等待服務器發送數據,並且服務器發送的內容都應保存到文件中。

這是我所做的:

頭文件

#ifndef MainH
#define MainH
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <FMX.Controls.hpp>
#include <FMX.Forms.hpp>
#include <FMX.Controls.Presentation.hpp>
#include <FMX.StdCtrls.hpp>
#include <FMX.Types.hpp>
#include <IdBaseComponent.hpp>
#include <IdComponent.hpp>
#include <IdIOHandler.hpp>
#include <IdIOHandlerStream.hpp>
#include <IdTCPClient.hpp>
#include <IdTCPConnection.hpp>
#include <boost/scoped_ptr.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE-managed Components
    TIdTCPClient *pTCP;
    TIdIOHandlerStream *IdIOHandlerStream;
    TButton *Button1;
    void __fastcall Button1Click(TObject *Sender);
    void __fastcall IdIOHandlerStreamGetStreams(TIdIOHandlerStream *ASender, TStream *&VReceiveStream, TStream *&VSendStream);
private:    // User declarations
    boost::scoped_ptr<TFileStream> mFile;
    boost::scoped_ptr<TMemoryStream> mMem;

    void __fastcall StopTcpClick(TObject* Sender);
public:     // User declarations
    __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

和CPP文件:

include <fmx.h>
#pragma hdrstop

#include "Main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.fmx"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner),
                            mFile(new TFileStream(L"C:\\IbsData.txt", fmCreate | fmOpenReadWrite | fmShareDenyWrite)),
                            mMem(new TMemoryStream())
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    pTCP->Connect();
    Button1->Text = L"Stop";
    Button1->OnClick = StopTcpClick;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::StopTcpClick(TObject* Sender)
{
    pTCP->Disconnect();
    Button1->Text = L"Start";
    Button1->OnClick = Button1Click;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdIOHandlerStreamGetStreams(TIdIOHandlerStream *ASender, TStream *&VReceiveStream, TStream *&VSendStream)
{
    VReceiveStream = mFile.get();
    VSendStream = mMem.get();
}

我必須注意, IdIOHandlerStream已設置為IOHandlerpTCP

問題是,我知道服務器正在發送大量數據,但是沒有任何內容寫入文件中。

有人知道為什么嗎?

您使用了錯誤的IOHandler類。

TIdIOHandlerStream使用TStream對象執行I / O。 它通常用於重放先前捕獲的會話以進行調試,而無需與真實服務器的物理連接。

您需要改用TIdIOHandlerStack ,它使用TCP / IP套接字連接執行I / O。 它是Indy的默認IOHandler類,因此您甚至不需要創建它的實例1 ,如果您不分配自己的實例, TIdTCPClient::Connect()將為您內部創建一個實例。

1:除非需要更高級的用法(例如通過代理連接到服務器等),否則您需要自己的實例,因此可以根據需要對其進行配置。

對於您要嘗試的操作,讓TIdTCPClient使用TIdIOHandlerStack ,然后在連接到服務器后可以調用TIdIOHandler::ReadStream()方法。 傳遞一個TFileStream以供其讀取,並將其AByteCount參數設置為-1並將AReadUntilDisconnect參數設置為True,這樣它將連續讀取直到套接字連接關閉。

同樣,就像Indy中的大多數操作一樣, ReadStream()阻塞調用線程直到完成,因此,為了避免阻塞UI,您應該在輔助線程中調用ReadStream() 但是,如果您不想使用線程,則可以替代地將TIdAntiFreeze組件放在窗體上。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM