• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 2788
  • Last Modified:

TClientSocket help

We are trying to write a program which uses a TClientSocket object to send a text string to an HTTP server and receive the response.

It seems so far that the socket is opened and data is sent to the server (apache logs confirm this). However, no data seems to be recevied and processed on the OnRead event. This does not even seem to be triggered.

Please note that this is Delphi 5.

Code below:

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
Form1.ClientSocket1.Active := True;
//clientsocket1.Open;
clientsocket1.Socket.SendText('GET http://www.getminted.com/Hello HTTP/1.1' + #13 + 'Host: www.getminted.com' + #13 + 'Connection: close' + #13 + #13 );
clientsocket1.socket.
FWaiting := true;
Application.MessageBox('SendText','', MB_OKCANCEL + MB_DEFBUTTON1) ;
while FWaiting do
Application.processmessages;
end;


procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
var
Buffer : array [0..4095] of char;
BytesReceived : integer;
MemoryStream : TMemoryStream;
begin
Application.MessageBox('ClientSocket1Read','', MB_OKCANCEL + MB_DEFBUTTON1) ;

  while FWaiting do
  begin
    MemoryStream := TMemoryStream.Create;
    try
     // Sleep(200);
      while True do
      begin
      BytesReceived := Socket.ReceiveBuf(Buffer,SizeOf(Buffer));
      if (BytesReceived <= 0) then
        Break
      else
      begin
      edit1.text := Buffer;
      MemoryStream.Write(Buffer,BytesReceived);
      end;

      end;
      FWaiting := False;
      MemoryStream.Position := 0;
   // XMLResponse.LoadFromStream(MemoryStream);
    finally
      MemoryStream.Free;
    end;
  end;
end;
0
wizard2000
Asked:
wizard2000
3 Solutions
 
RHenningsgardCommented:
If you're getting connected to port 80 of the web server and getting no response to your GET, then your GET isn't formatted correctly.  You may find the easiest way to get it right is to observe in detail how a web browser formats its GET and then duplicate that precisely.

I recommend the following:

1) Get a copy of Ethereal (see http://www.ethereal.com ) and install it on the machine on which you're running your Delphi test application.

2) Run Ethereal, capturing your own network traffic, with the filter "port 80".

3) Use a web browser (like IE) to fetch the URL you're trying to get with your Delphi application.

4) Read the Ethereal log to see precisely how the GET is formatted by IE, then duplicate that precisely in your application.

In the process, you'll both figure out what your application is doing wrong, and you'll learn to use a very powerful diagnostic tool (one you're going to want sooner or later anyhow).

Rob---
0
 
RHenningsgardCommented:
For what it's worth, I think I've always seen web browsers use both #13 carriage return and #10 line feed for terminators, i.e.

clientsocket1.Socket.SendText('GET http://www.getminted.com/Hello HTTP/1.1' + #13#10 + 'Host: www.getminted.com' + #13#10 + 'Connection: close' + #13#10#13#10 );

That might be the problem.

Rob
0
 
RHenningsgardCommented:
I just got curious and did what I recommended to you.  Here's what IE did with your test URL.  Note that the URL is "/Hello", not "http://www.getminted.com/Hello" for one thing.

GET /Hello HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/x-shockwave-flash, */*
Accept-Language: en-us
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; (R1 1.5))
Host: www.getminted.com
Connection: Keep-Alive
Extension: Security/Remote-Passphrase

Rob---
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
wizard2000Author Commented:
Yep but the thing is, if you do it from a telnet prompt (on a unix machine at least) you get data back. IE just using
GET /Hello HTTP/1.0
Host: www.getminted.com

(note 2 returns to terminate the data)

This returns 'stuff' - thing is im not getting the onread event triggered which as far as im concerned it should be. The additional stuff is not needed to get a response from the server so shouldent be need to trigger the onread as far as i can see.

Why is it not triggering?!?! Driving me nuts... BTW I started using 13 10 as the term chars but it makes no difference.

And, strangest of all, apache is showing the request in the logs. As an error, but a raw socket shouldent be aware of that.
0
 
wizard2000Author Commented:
Unfortunatly ethereal just crashes as soon as its started...
0
 
BlackTigerXCommented:
right... you don't send the whole www... after the GET everytime, just the URL from the root point, in this case "/Hello"

in any case... shouldn't you get a response back saying at least error or something?
0
 
wizard2000Author Commented:
Exactly! Damn event should be triggered... I have a messagebox alert first thing in the onread event but it never gets called, program just gets stuck in the application.processmessages bit.

Normally im a unix / perl coder so this is a bit out of my experience... but do you guys concur this should be right?
0
 
DragonSlayerCommented:
I did it the blocking way, and it seems to work:

procedure TForm1.Button1Click(Sender: TObject);
var
  Command: string;
  retBuf: array [0 .. 4095] of Char;
  iReturn: Integer;
begin
  Memo1.Clear;
  with ClientSocket1 do
  begin
    Host := '213.152.247.17'; // www.getminted.com
    ClientType := ctBlocking;
    Port := 80;

    try
      Open;
      Command := 'GET /Hello HTTP/1.1'#13#10 +
        'Host: www.getminted.com'#13#10#13#10;
      iReturn := Socket.SendBuf(Pointer(Command)^, Length(Command));
      if iReturn > 0 then
      begin
        while iReturn > 0 do
        begin
          FillChar(retBuf, SizeOf(retBuf), 0);
          iReturn := Socket.ReceiveBuf(retBuf, SizeOf(retBuf));
          if iReturn > 0 then
            Memo1.Lines.Add(retBuf);
        end;
      end else
        raise Exception.Create('Server not responding!');
    except
      on E: Exception do
        ShowMessage('Error at ' + E.Message);
    end;
  end;
end;




DragonSlayer.
0
 
mgazzaCommented:
geez iv just wrote thius out once and agen by the looks  why are you using components!!


var
zero:cardinal=0;
procedure HTTPs(URL,Headers:PChar;var OutHeaders, OutDoc:string);

var
  RequestHandle,IOpenHandle : PHandle;
  DataWritten:cardinal;
  buffer:array[0..100] of char;
begin

  IOpenHandle:= InternetOpen('Mozilla/4.0 (compatible)', INTERNET_OPEN_TYPE_PRECONFIG , NIL, NIL, 0);

  // open the file
  RequestHandle:=InternetOpenUrl(iOpenHandle, URL, Headers, length(Headers),
                          INTERNET_FLAG_RAW_DATA or INTERNET_FLAG_SECURE,0);

  if RequestHandle<>nil then begin
   repeat
     if InternetReadFile(RequestHandle,@buffer[0],sizeof(buffer),DataWritten) then
        OutDoc:=OutDoc+copy(buffer,0,DataWritten) else break;
   until DataWritten=0;
   setlength(outheaders,512);
   repeat
    DataWritten:=length(outheaders);
     if HttpQueryInfoA(RequestHandle, HTTP_QUERY_RAW_HEADERS_CRLF, @outheaders[1],DataWritten,zero) then begin
      setlength(outheaders,datawritten);
      break;
     end
     else setlength(outheaders,datawritten*2);
    until datawritten=1024*5;

  end;

  InternetCloseHandle(requestHandle);
  InternetCloseHandle(IOpenHandle);
end;

procedure HTTP(URL,Headers:PChar;var OutHeaders, OutDoc:string);

var
  RequestHandle,IOpenHandle : PHandle;
  DataWritten:cardinal;
  buffer:array[0..100] of char;
begin

  IOpenHandle:= InternetOpen('Mozilla/4.0 (compatible)', INTERNET_OPEN_TYPE_PRECONFIG , NIL, NIL, 0);

  // open the file
  RequestHandle:=InternetOpenUrl(iOpenHandle, URL, Headers, length(Headers),
                          INTERNET_FLAG_RAW_DATA,0);

  if RequestHandle<>nil then begin
   repeat
     if InternetReadFile(RequestHandle,@buffer[0],sizeof(buffer),DataWritten) then
        OutDoc:=OutDoc+copy(buffer,0,DataWritten) else break;
   until DataWritten=0;
   setlength(outheaders,512);
   repeat
    DataWritten:=length(outheaders);
     if HttpQueryInfoA(RequestHandle, HTTP_QUERY_RAW_HEADERS_CRLF, @outheaders[1],DataWritten,zero) then begin
      setlength(outheaders,datawritten);
      break;
     end
     else setlength(outheaders,datawritten*2);
    until datawritten=1024*5;

  end;

  InternetCloseHandle(requestHandle);
  InternetCloseHandle(IOpenHandle);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
Head:Pchar;
d,h:string;
begin

https('https://www.google.com/,nil,h,d);
or
http('http://www.google.com/,nil,h,d);

showmessage(h+d)

end;
0
 
wizard2000Author Commented:
erm, i accepted an answer days ago... why was this changed?
0

Featured Post

New feature and membership benefit!

New feature! Upgrade and increase expert visibility of your issues with Priority Questions.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now