INDY 9有tidtcpclient  ,   tidtcpserver  ,  tidudpclient  ,  tidudpserver
其中tidtcpserver  , tidudpserver 都有处理接收数据的事件分别是OnExecute 和OnUDPRead用来处理客户端发送过来的数据,就如同BORLAND自带的winsocket控件和NMUDP控件处理onread   ondatareceive这些事件等等。但是tidtcpclient  ,  tidudpclient  没有这些事件,我的问题是如何给tidtcpclient  ,  tidudpclient 添加上实现接收数据并处理数据的功能,尤其是服务器主动发送数据包给客户端的时候。

解决方案 »

  1.   

    采用线程,看它的源代码,server也是通过一个线程来读取数据的,然后生成事件
      

  2.   

    如果要求不是很高,你可以设置一个TTimer在OnTimer事件中读取数据。要是要求精确控制,那就需要从TThread继承一个工作线程类,重载其Excute方法,在方法中循环从TIdTCPClient中读取数据。
    BTW,Indy是阻塞的,所以如果没有数据到达的话工作线程会停在那,直到读到数据或者出现异常。
      

  3.   

    如果用TIMER的话,代码如下的话:
    ontimer( )
    {readln( );//或者是receivestring( )<----------假如没有数据到达的话,就会一直停在这里么?直到有数据到达,才继续执行吗?TThread也是如此吗?
    }我用的是BCB,兼用DELPHI,还有tthread是BORLAND里面的tthread还是INDY里面的tidthread呢?如果是用线程的话能详细说说?顺便给个例子代码。很感谢啊!
      

  4.   

    前几天心血来潮用BCB6改写了一个Indy9里面带的Demo,代码有点长,给个地址我发过去。
      

  5.   

    WinSocket收发数据有两种模式:Blocking和Non-Blocking,Indy就被设计成Blocking模式的。当你在某个线程中调用Indy组件的接口去发送/读取数据的时候,这个线程就会停在那里,一直到数据发送/读取完成或者是出现异常,才会继续执行下面的指令。如果你用TTimer来控制收发数据,那么有必要在客户端窗体上放一个TIdAntiFreeze控件,据说是用来防止主线程冻结的。不过我不知道是不是真的管用,因为我不用它也没发现我的客户端窗口冻住过。
    贴一段使用TThread的代码://---------------------------------------------------------------------------
    /* 头文件 ClientThread.h */#ifndef ClientThreadH
    #define ClientThreadH
    //---------------------------------------------------------------------------
    #include <Classes.hpp>
    #include "ClientFrm.h"
    //---------------------------------------------------------------------------
    class TClientThread : public TThread
    {            
    private:
        TfrmClient *FMainForm;
        AnsiString FUserName;
        AnsiString FMsgString;
        bool FMsgFlag;
    protected:
        void __fastcall Execute();
        void __fastcall DoWriteMsg();
    public:
        __fastcall TClientThread(TfrmClient *AForm, bool CreateSuspended);
    };
    //---------------------------------------------------------------------------
    #endif
      

  6.   

    /* 实现文件 ClientThread.cpp */
    //---------------------------------------------------------------------------#include <vcl.h>
    #pragma hdrstop#include "ClientThread.h"
    #include "ClientFrm.h"
    #pragma package(smart_init)
    //---------------------------------------------------------------------------__fastcall TClientThread::TClientThread(TfrmClient *AForm, bool CreateSuspended)
        : TThread(CreateSuspended)
    {
        FMainForm = AForm;
        FUserName = FMainForm->edt_Name->Text;
        FreeOnTerminate = true;
    }
    //---------------------------------------------------------------------------
    void __fastcall TClientThread::DoWriteMsg()
    {
        FMainForm->WriteMsg(FMsgString, FMsgFlag);
    }
    //---------------------------------------------------------------------------
    void __fastcall TClientThread::Execute()
    {
        //---- Place thread code here ----
        TIdTCPClient *AClient = FMainForm->tcpClient;
        while(!Terminated && AClient->Connected())
        {
            try
            {
                FMsgString = AClient->ReadLn("");
            }
            catch(...)
            {
                MessageBox(FMainForm->Handle, "AClient->ReadLn() Failed!",
                    "TClientThread", MB_OK);
                Terminate();
                break;
            }
            
            if(FMsgString.Length() < 5
                || FMsgString.Pos("@") != 1
                || FMsgString.Pos(":") != 5) continue;
            AnsiString strCmd = UpperCase(FMsgString.SubString(2, 3));
            if(strCmd == "BYE")
            {
                AClient->Disconnect();
                FMsgString = "TClientThread::Excute() 同服务器的连接已经断开。";
                FMsgFlag = true;
                Synchronize(DoWriteMsg);
                break;
            }
            else if(strCmd == "WEL")
            {
                FMsgString = "正在发送登录名称...";
                FMsgFlag = true;
                Synchronize(DoWriteMsg);
                AClient->WriteLn("@REN:" + FUserName);
                FMsgString = "发送成功,已经完成登录!";
                FMsgFlag = true;
                Synchronize(DoWriteMsg);
            }
            else if(strCmd == "MSG" || strCmd == "SYS")
            {
                if(FMsgString.Length() > 5)
                {
                    FMsgString = FMsgString.SubString(6, FMsgString.Length() - 5);
                    if(strCmd == "MSG")
                        FMsgFlag = false;
                    else
                        FMsgFlag = true;
                    Synchronize(DoWriteMsg);
                }
            }
        }
    }
    //---------------------------------------------------------------------------