代码之家  ›  专栏  ›  技术社区  ›  Sam

使用tidiohandlerstream和tidtcpclient读取数据流

  •  0
  • Sam  · 技术社区  · 6 年前

    我有一个应用程序需要使用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
    

    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 IOHandler 属于 pTCP .

    问题是,我知道服务器正在发送大量数据,但没有任何数据写入文件。

    有人知道为什么吗?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Remy Lebeau    6 年前

    您使用的IOHandler类不正确。

    TIdIOHandlerStream 使用 TStream 物体。它通常用于重放先前捕获的会话以进行调试,而不需要与真正的服务器进行物理连接。

    你需要使用 TIdIOHandlerStack 相反,它使用TCP/IP套接字连接来执行I/O。它是indy的默认iohandler类,因此您甚至不需要创建它的实例。 , TIdTCPClient::Connect() 如果不分配自己的,将在内部为您创建一个。

    1:除非您需要更高级的用法,如通过代理服务器连接到服务器等,否则您需要自己的实例,以便根据需要进行配置。

    为了你想要的,让 TIdTCPClient 使用 Tidiohandlerstack公司 然后你可以打电话给 TIdIOHandler::ReadStream() 方法。传球 TFileStream 让它读取并设置 AByteCount 参数-1和 AReadUntilDisconnect 参数设置为“真”,这样它将连续读取,直到套接字连接关闭。

    而且,像印地的大多数业务一样, ReadStream() 在完成之前阻塞调用线程,因此为了避免阻塞UI,应该调用 读流() 在工作线程中。但是,如果不想使用线程,可以交替地将 TIdAntiFreeze 而不是窗体上的组件。

    推荐文章