download files from the internet through events

This is the forum for miscellaneous technical/programming questions.

Moderator: 2ffat

download files from the internet through events

Postby mark_c » Tue Sep 03, 2019 2:03 am

Hello,
with this example, I noticed that using the BCB OnRead event is not possible to determine the end of the file, is it correct?

Code: Select all
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"

AnsiString MyBuffer;
AnsiString MyHost="www.google.com";

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
        ClientSocket1->Active = false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
        ClientSocket1->Host = MyHost;
        ClientSocket1->Port = 80;
        if(ClientSocket1->Active == true) ClientSocket1->Active = false;
        ClientSocket1->Active = true;
        Memo1->Clear();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientSocket1Read(TObject *Sender,
      TCustomWinSocket *Socket)
{
        char *buffer;
        int  buffer_len;

        // get the message length
        buffer_len = Socket->ReceiveLength();
        // create a new buffer big
        // enough to contain the message
        buffer = new char[buffer_len];
        // get the message
        if (Socket->ReceiveBuf(buffer, buffer_len) == -1)
        {
                ShowMessage ("No message received or EOF???");
                ClientSocket1->Active = False;
                // free the buffer
                delete[] buffer;
                return;
        }
        Memo1->Lines->Add(buffer);

        // free the buffer
        delete[] buffer;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::ClientSocket1Connect(TObject *Sender,
      TCustomWinSocket *Socket)
{
        ClientSocket1->Socket->SendText("GET / HTTP/1.1\r\nHost: "+MyHost+"\r\n\r\n");
}
//---------------------------------------------------------------------------

void __fastcall TForm1::ClientSocket1Connecting(TObject *Sender,
      TCustomWinSocket *Socket)
{
        RadioButton1->Checked=true;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::ClientSocket1Disconnect(TObject *Sender,
      TCustomWinSocket *Socket)
{
        RadioButton1->Checked=false;
}
//---------------------------------------------------------------------------

mark_c
BCBJ Guru
BCBJ Guru
 
Posts: 166
Joined: Thu Jun 21, 2012 1:13 am

Re: download files from the internet through events

Postby HsiaLin » Tue Sep 03, 2019 7:39 am

If you are just wanting to download files, would be easier to just edit the source
from this thread.

http://bcbjournal.org/forums/viewtopic.php?f=10&t=3182
HsiaLin
BCBJ Master
BCBJ Master
 
Posts: 316
Joined: Sun Jul 08, 2007 6:29 pm

Re: download files from the internet through events

Postby rlebeau » Tue Sep 03, 2019 1:05 pm

mark_c wrote:with this example, I noticed that using the BCB OnRead event is not possible to determine the end of the file, is it correct?


Yes, it is possible, just not the way you have coded it.

You are sending an HTTP 1.1 request, and by default HTTP 1.1 uses keep-alives, meaning the TCP connection is left open after the response has been sent/consumed, unless the HTTP client explicitly requests otherwise, or the HTTP server has keep-alives disabled. Closing the connection at the end of the response is only one possible scenario when dealing with HTTP, and frankly it is not a very common one nowadays, or the preferred way. However, you CAN force it, by explicitly asking in your GET request that no keep-alive be used:

Code: Select all
ClientSocket1->Socket->SendText("GET / HTTP/1.1\r\nHost: "+MyHost+"\r\nConnection: close\r\n\r\n");


But, you really shouldn't rely on this. What you should be doing instead is actually PARSING THE RESPONSE according to the rules of the HTTP protocol. In particular, RFC 2616 section 4.4 (and later, RFC 7230 section 3.3.3) describes exactly how to determine when a response has ended. You need to read the HTTP response headers first until you encounter the terminating "\r\n\r\n" sequence, then parse the headers to determine how to read the rest of the response so yo know when to stop reading.

That CAN be done with the OnRead logic you have, albeit not in one go. You need a state machine, adding raw bytes received to your MyBuffer variable as they come in, and parsing it along the way until you detect the end of the response according to the HTTP protocol, and then you can do whatever you want with the received body content.

That being said, there are some logic bugs in the code that you currently have!

  • not checking to make sure that SendText() actually sends the complete request (FYI, it is not a guarantee!)
  • not checking for errors on ReceiveLength() before allocating memory
  • ignoring the return value of ReceiveBuf(), which tells you how many bytes were actually read. You are assuming the buffer is always null-terminated (FYI, it never is!)

Try something more like this:

Code: Select all
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"

AnsiString MyBuffer;
AnsiString MyHost = "www.google.com";

enum eParsingState {ReadingStatus, ReadingHeaders, ReadingBody, EndOfResponse};
eParsingState ParsingState;

enum eBodyState {ReadingBodyByChunks, ReadingBodyUntilLength, ReadingBodyUntilClose};
eBodyState BodyState;

enum eChunkState {ReadingChunkHeader, ReadingChunkData, ReadingChunkDataCRLF, ReadingChunksTrailer};
eChunkState ChunkState;

__int64 BytesRemaining = 0;

int StatusCode;
TStringList *Headers;

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
      : TForm(Owner)
{
   Headers = new TStringList;
   Headers->NameValueSeparator = ':';
   Headers->CaseSensitive = false;
}
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
      : TForm(Owner)
{
   delete Headers;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
   ClientSocket1->Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   ClientSocket1->Close();
   ClientSocket1->Host = MyHost;
   ClientSocket1->Port = 80;
   ClientSocket1->Open();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientSocket1Error(TObject *Sender,
   TCustomWinSocket* Socket, TErrorEvent ErrorEvent, int &ErrorCode)
{
   ErrorCode = 0;
   Socket->Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientSocket1Read(TObject *Sender,
   TCustomWinSocket *Socket)
{
   int  buffer_len = Socket->ReceiveLength();
   if (buffer_len <= 0) return;

   AnsiString buffer;
   buffer.SetLength(buffer_len);

   buffer_len = Socket->ReceiveBuf(buffer.c_str(), buffer_len);
   if (buffer_len <= 0) return;

   buffer.SetLength(buffer_len);

   //Memo1->Lines->Add(buffer);
   Memo1->SelStart = Memo1->GetTextLen();
   Memo1->SelLength = 0;
   Memo1->SelText = buffer;

   MyBuffer += buffer;
   UpdateState();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::UpdateState()
{
   do
   {
      switch (ParsingState)
      {
         case ReadingStatus:
         {
            // clear body storage as needed...

            int Term = MyBuffer.Pos("\r\n");
            if (Term == 0) return;

            String StatusLine = MyBuffer.SubString(1, Term-1);
            MyBuffer.Delete(1, Term+1);

            Term = StatusLine.Pos(" ");
            StatusLine.Delete(1, Term); // HTTP-Version
            
            Term = StatusLine.Pos(" ");
            StatusCode = StatusLine.SubString(1, Term-1).Trim().ToInt();
               
            Headers->Clear();

            ParsingState = ReadingHeaders;
            break;
         }

         case ReadingHeaders:
         {
            int Term = MyBuffer.Pos("\r\n\r\n");
            if (Term == 0) return;

            Headers->Text = MyBuffer.SubString(1, Term-1);
            MyBuffer.Delete(1, Term+3);

            if (/*(Request was "HEAD") ||*/ ((StatusCode / 100) == 1) || (StatusCode == 204) || (StatusCode == 304))
            {
               ParsingState = EndOfResponse;
               break;
            }

            String TransferEncoding = Headers->Values["Transfer-Encoding"].Trim();
            if ((TransferEncoding != "") && !SameText(TransferEncoding, "identity"))
            {
               BodyState = ReadingBodyByChunks;
               ChunkState = ReadingChunkHeader;
            }
            else
            {
               BytesRemaining = StrToInt64Def(Headers->Values["Content-Length"].Trim(), -1);
               if (BytesRemaining >= 0)
                  BodyState = ReadingBodyUntilLength;
               else
                  BodyState = ReadingBodyUntilClose;
            }

            ParsingState = ReadingBody;
            break;
         }

         case ReadingBody:
         {
            switch (BodyState)
            {
               case ReadingBodyByChunks:
               {
                  switch (ChunkState)
                  {
                     case ReadingChunkHeader:
                     {
                        int Term = MyBuffer.Pos("\r\n");
                        if (Term == 0) return;

                        AnsiString Line = MyBuffer.SubString(1, Term-1);
                        MyBuffer.Delete(1, Term+1);

                        Term = Line.Pos(";");
                        if (Term != 0) Line.SetLength(Term-1);

                        BytesRemaining = StrToInt64("0x" + Line);
                        if (BytesRemaining > 0)
                           ChunkState = ReadingChunkData;
                        else
                           ChunkState = ReadingChunksTrailer;

                        break;
                     }

                     case ReadingChunkData:
                     {
                        if (MyBuffer.Length() < BytesRemaining)
                        {
                           // save all of MyBuffer bytes to body storage as needed...

                           BytesRemaining -= MyBuffer.Length();
                           MyBuffer = "";

                           return;
                        }

                        // save MyBuffer up to BytesRemaining bytes to body storage as needed...

                        MyBuffer.Delete(1, BytesRemaining);
                        BytesRemaining = 0;

                        ChunkState = ReadingChunkDataCRLF;
                        break;
                     }

                     case ReadingChunkDataCRLF:
                     {
                        int Term = MyBuffer.Pos("\r\n");
                        if (Term == 0) return;

                        MyBuffer.Delete(1, Term+1);

                        ChunkState = ReadingChunkHeader;
                        break;
                     }

                     case ReadingChunksTrailer:
                     {
                        int Term = MyBuffer.Pos("\r\n");
                        if (Term == 0) return;

                        AnsiString Header = MyBuffer.SubString(1, Term-1).Trim();
                        MyBuffer.Delete(1, Term+1);

                        if (Header == "")
                        {
                           ParsingState = EndOfResponse;
                           break;
                        }

                        // update Headers with Header data as needed...

                        break;
                     }
                  }
                  
                  break;
               }

               case ReadingBodyUntilLength:
               {
                  if (MyBuffer.Length() < BytesRemaining)
                  {
                     // save all of MyBuffer bytes to body storage as needed...
                     
                     BytesRemaining -= MyBuffer.Length();
                     MyBuffer = "";

                     return;
                  }

                  // save MyBuffer up to BytesRemaining bytes to body storage as needed...

                  while (BytesRemaining > MaxInt)
                  {
                     MyBuffer.Delete(1, MaxInt);
                     BytesRemaining -= MaxInt;
                  }
                  MyBuffer.Delete(1, (int) BytesRemaining);
                  BytesRemaining = 0;

                  ParsingState = EndOfResponse;
                  break;
               }

               case ReadingBodyUntilClose:
               {
                  // save all of MyBuffer bytes to body storage as needed...

                  MyBuffer = "";
                  return;
               }
            }

            break;
         }

         case EndOfResponse:
         {
            ProcessResponse();
            ParsingState = ReadingStatus;
            break;
         }
      }
   }
   while (true);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ProcessResponse()
{
   // process StatusCode, Headers, and body storage as needed...

   if (SameText(Headers->Values["Connection"].Trim(), "close"))
      ClientSocket1->Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientSocket1Connect(TObject *Sender,
     TCustomWinSocket *Socket)
{
   Memo1->Clear();
   MyBuffer = "";

   //AnsiString Request = "GET / HTTP/1.1\r\nHost: " + MyHost + "\r\nConnection: close\r\n\r\n";
   AnsiString Request = "GET / HTTP/1.1\r\nHost: " + MyHost + "\r\n\r\n";
   char *buffer = Request.c_str();
   int buffer_len = Request.Length();

   int sent;
   do
   {
      sent = ClientSocket1->Socket->SendBuf(buffer, buffer_len);
      if (sent == -1)
      {
         ClientSocket1->Close();
         return;
      }
      buffer += sent;
      buffer_len -= sent;
   }
   while (buffer_len > 0);

   ParsingState = ReadingStatus;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientSocket1Connecting(TObject *Sender,
   TCustomWinSocket *Socket)
{
   RadioButton1->Checked = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientSocket1Disconnect(TObject *Sender,
   TCustomWinSocket *Socket)
{
   RadioButton1->Checked = false;
   Socket->Close();

   if ((ParsingState == ReadingBody) && (BodyState == ReadingBodyUntilClose))
      ProcessResponse();
}
//---------------------------------------------------------------------------


But why are you using TClientSocket for handling HTTP? That is not a good choice. HTTP is a complex protocol, especially in an asynchronous mode like you are trying to use. You really should be using a pre-existing HTTP library/API instead, such as Microsoft's WinInet/WinHTTP, or Indy's TIdHTTP component, or any number of other 3rd party HTTP client APIs that are readably available.
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1605
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: download files from the internet through events

Postby mark_c » Thu Sep 05, 2019 4:47 am

thanks Remy, as always, very clear
mark_c
BCBJ Guru
BCBJ Guru
 
Posts: 166
Joined: Thu Jun 21, 2012 1:13 am

Re: download files from the internet through events

Postby mark_c » Mon Sep 09, 2019 8:26 am

hi Remy,
am I wrong or writing code in this way are you turning a non blocking socket into a blocking socket?

This is because the while loop is not abandoned until the message is completely sent; if it is not so, as not said.

Code: Select all
   do
   {
      sent = ClientSocket1->Socket->SendBuf(buffer, buffer_len);
      if (sent == -1)
      {
         ClientSocket1->Close();
         return;
      }
    
      buffer += sent;
      buffer_len -= sent;
   }
   while (buffer_len > 0);
mark_c
BCBJ Guru
BCBJ Guru
 
Posts: 166
Joined: Thu Jun 21, 2012 1:13 am

Re: download files from the internet through events

Postby rlebeau » Tue Sep 10, 2019 1:43 pm

mark_c wrote:am I wrong or writing code in this way are you turning a non blocking socket into a blocking socket?


No, it is not. It is sending as much data as the socket will accept WITHOUT it blocking, and as soon as it errors for any reason, INCLUDING blocking (when the error is WSAEWOULDBLOCK), the loop is stopped and the socket is closed, for demonstration purposes since I was focusing more on showing the logic to parse the server's response, rather than the logic to send a request.

The proper way to take non-blocking sends into account in this code would be to cache the remaining unsent data on a blocking error and then wait for the OnWrite event to be fired before sending the cache and any subsequent data, repeating as needed until the cache is empty.

Here is the updated code including outbound caching:

Code: Select all
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"

AnsiString InboundBuffer;
AnsiString OutboundBuffer;
AnsiString MyHost = "www.google.com";

enum eParsingState {ReadingStatus, ReadingHeaders, ReadingBody, EndOfResponse};
eParsingState ParsingState;

enum eBodyState {ReadingBodyByChunks, ReadingBodyUntilLength, ReadingBodyUntilClose};
eBodyState BodyState;

enum eChunkState {ReadingChunkHeader, ReadingChunkData, ReadingChunkDataCRLF, ReadingChunksTrailer};
eChunkState ChunkState;

__int64 BytesRemaining = 0;

int StatusCode;
TStringList *Headers;

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
   : TForm(Owner)
{
   Headers = new TStringList;
   Headers->NameValueSeparator = ':';
   Headers->CaseSensitive = false;
}
//---------------------------------------------------------------------------
__fastcall TForm1::~TForm1()
{
   delete Headers;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
   ClientSocket1->Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   ClientSocket1->Close();
   ClientSocket1->Host = MyHost;
   ClientSocket1->Port = 80;
   ClientSocket1->Open();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientSocket1Error(TObject *Sender,
   TCustomWinSocket* Socket, TErrorEvent ErrorEvent, int &ErrorCode)
{
   ErrorCode = 0;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientSocket1Read(TObject *Sender,
   TCustomWinSocket *Socket)
{
   int buffer_len = Socket->ReceiveLength();
   if (buffer_len <= 0) return;

   AnsiString buffer;
   buffer.SetLength(buffer_len);

   buffer_len = Socket->ReceiveBuf(buffer.c_str(), buffer_len);
   if (buffer_len <= 0) return;

   buffer.SetLength(buffer_len);

   //Memo1->Lines->Add(buffer);
   Memo1->SelStart = Memo1->GetTextLen();
   Memo1->SelLength = 0;
   Memo1->SelText = buffer;

   InboundBuffer += buffer;
   UpdateState();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::UpdateState()
{
   do
   {
      switch (ParsingState)
      {
         case ReadingStatus:
         {
            // clear body storage as needed...

            int Term = InboundBuffer.Pos("\r\n");
            if (Term == 0) return;

            String StatusLine = InboundBuffer.SubString(1, Term-1);
            InboundBuffer.Delete(1, Term+1);

            Term = StatusLine.Pos(" ");
            StatusLine.Delete(1, Term); // HTTP-Version
            
            Term = StatusLine.Pos(" ");
            StatusCode = StatusLine.SubString(1, Term-1).Trim().ToInt();

            Headers->Clear();

            ParsingState = ReadingHeaders;
            break;
         }

         case ReadingHeaders:
         {
            int Term = InboundBuffer.Pos("\r\n\r\n");
            if (Term == 0) return;

            Headers->Text = InboundBuffer.SubString(1, Term-1);
            InboundBuffer.Delete(1, Term+3);

            // TODO: keep track of what kind of request is being responded to...
            if (/*(Request was "HEAD") ||*/ ((StatusCode / 100) == 1) || (StatusCode == 204) || (StatusCode == 304))
            {
               ParsingState = EndOfResponse;
               break;
            }

            String TransferEncoding = Headers->Values["Transfer-Encoding"].Trim();
            if ((!TransferEncoding.IsEmpty()) && !SameText(TransferEncoding, "identity"))
            {
               BodyState = ReadingBodyByChunks;
               ChunkState = ReadingChunkHeader;
            }
            else
            {
               AnsiString value = Headers->Values["Content-Length"].Trim();
               if (!value.IsEmpty())
               {
                  BytesRemaining = StrToInt64(value);
                  BodyState = ReadingBodyUntilLength;
               }
               else
                  BodyState = ReadingBodyUntilClose;
            }

            ParsingState = ReadingBody;
            break;
         }

         case ReadingBody:
         {
            switch (BodyState)
            {
               case ReadingBodyByChunks:
               {
                  switch (ChunkState)
                  {
                     case ReadingChunkHeader:
                     {
                        int Term = InboundBuffer.Pos("\r\n");
                        if (Term == 0) return;

                        AnsiString Line = InboundBuffer.SubString(1, Term-1);
                        InboundBuffer.Delete(1, Term+1);

                        Term = Line.Pos(";");
                        if (Term != 0) Line.SetLength(Term-1);

                        BytesRemaining = StrToInt64("0x" + Line);
                        if (BytesRemaining > 0)
                           ChunkState = ReadingChunkData;
                        else
                           ChunkState = ReadingChunksTrailer;

                        break;
                     }

                     case ReadingChunkData:
                     {
                        if (InboundBuffer.Length() < BytesRemaining)
                        {
                           // save all of InboundBuffer bytes to body storage as needed...

                           BytesRemaining -= InboundBuffer.Length();
                           InboundBuffer = "";

                           return;
                        }

                        // save InboundBuffer up to BytesRemaining bytes to body storage as needed...

                        InboundBuffer.Delete(1, BytesRemaining);
                        BytesRemaining = 0;

                        ChunkState = ReadingChunkDataCRLF;
                        break;
                     }

                     case ReadingChunkDataCRLF:
                     {
                        int Term = InboundBuffer.Pos("\r\n");
                        if (Term == 0) return;

                        InboundBuffer.Delete(1, Term+1);

                        ChunkState = ReadingChunkHeader;
                        break;
                     }

                     case ReadingChunksTrailer:
                     {
                        int Term = InboundBuffer.Pos("\r\n");
                        if (Term == 0) return;

                        AnsiString Header = InboundBuffer.SubString(1, Term-1).Trim();
                        InboundBuffer.Delete(1, Term+1);

                        if (Header == "")
                        {
                           ParsingState = EndOfResponse;
                           break;
                        }

                        // update Headers with Header data as needed...

                        break;
                     }
                  }
                  
                  break;
               }

               case ReadingBodyUntilLength:
               {
                  if (InboundBuffer.Length() < BytesRemaining)
                  {
                     // save all of InboundBuffer bytes to body storage as needed...
                     
                     BytesRemaining -= InboundBuffer.Length();
                     InboundBuffer = "";

                     return;
                  }

                  // save InboundBuffer up to BytesRemaining bytes to body storage as needed...

                  while (BytesRemaining > MaxInt)
                  {
                     InboundBuffer.Delete(1, MaxInt);
                     BytesRemaining -= MaxInt;
                  }
                  InboundBuffer.Delete(1, (int) BytesRemaining);
                  BytesRemaining = 0;

                  ParsingState = EndOfResponse;
                  break;
               }

               case ReadingBodyUntilClose:
               {
                  // save all of InboundBuffer bytes to body storage as needed...

                  InboundBuffer = "";
                  return;
               }
            }

            break;
         }

         case EndOfResponse:
         {
            ProcessResponse();
            ParsingState = ReadingStatus;
            break;
         }
      }
   }
   while (true);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ProcessResponse()
{
   // process StatusCode, Headers, and body storage as needed...

   // TODO: parse the version number from the response StatusLine...
   if (/*HTTP version is 1.1+*/true)
   {
      if (SameText(Headers->Values["Connection"].Trim(), "close"))
         ClientSocket1->Close();
   }
   else
   {
      if (!SameText(Headers->Values["Connection"].Trim(), "keep-alive"))
         ClientSocket1->Close();
   }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientSocket1Write(TObject *Sender,
   TCustomWinSocket *Socket)
{
   while (!OutboundBuffer.IsEmpty())
   {
      int sent = ClientSocket1->Socket->SendBuf(OutboundBuffer.c_str(), OutboundBuffer.Length());
      if (sent == -1)
         return;

      OutboundBuffer.Delete(1, sent);
   }   
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientSocket1Connect(TObject *Sender,
     TCustomWinSocket *Socket)
{
   Memo1->Clear();
   InboundBuffer = "";
   OutboundBuffer = "";

   ParsingState = ReadingStatus;

   AnsiString Request = "GET / HTTP/1.1\r\nHost: " + MyHost + "\r\n" /*"Connection: close\r\n"*/ "\r\n";
   SendRequest(Request);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::SendRequest(const AnsiString &Request)
{
   if (!OutboundBuffer.IsEmpty())
   {
      OutboundBuffer += Request;
      return;
   }

   char *buffer = Request.c_str();
   int buffer_len = Request.Length();

   do
   {
      int sent = ClientSocket1->Socket->SendBuf(buffer, buffer_len);
      if (sent == -1)
      {
         OutboundBuffer += AnsiString(buffer, buffer_len);
         return;
      }

      buffer += sent;
      buffer_len -= sent;
   }
   while (buffer_len > 0);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientSocket1Connecting(TObject *Sender,
   TCustomWinSocket *Socket)
{
   RadioButton1->Checked = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientSocket1Disconnect(TObject *Sender,
   TCustomWinSocket *Socket)
{
   RadioButton1->Checked = false;
   Socket->Close();

   if ((ParsingState == ReadingBody) && (BodyState == ReadingBodyUntilClose))
      ProcessResponse();
}
//---------------------------------------------------------------------------
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1605
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA


Return to Technical

Who is online

Users browsing this forum: No registered users and 21 guests