Solved

TClientSocket help

Posted on 2004-09-03
14
2,626 Views
Last Modified: 2012-06-27
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
Comment
Question by:wizard2000
14 Comments
 
LVL 2

Expert Comment

by:RHenningsgard
ID: 11973444
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
 
LVL 2

Expert Comment

by:RHenningsgard
ID: 11973467
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
 
LVL 2

Accepted Solution

by:
RHenningsgard earned 84 total points
ID: 11973529
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
 
LVL 1

Author Comment

by:wizard2000
ID: 11973620
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
 
LVL 1

Author Comment

by:wizard2000
ID: 11973642
Unfortunatly ethereal just crashes as soon as its started...
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 13

Expert Comment

by:BlackTigerX
ID: 11973667
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
 
LVL 1

Author Comment

by:wizard2000
ID: 11973720
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
 
LVL 14

Assisted Solution

by:DragonSlayer
DragonSlayer earned 83 total points
ID: 11987794
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
 
LVL 1

Assisted Solution

by:mgazza
mgazza earned 83 total points
ID: 12092801
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
 
LVL 1

Author Comment

by:wizard2000
ID: 13437522
erm, i accepted an answer days ago... why was this changed?
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
PDF library for Delphi 2 104
Delphi: how to implement a User Shortcut mapper? 1 94
creating threads in delphi 1 82
control image tags in a string ? 12 110
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
This Micro Tutorial will teach you how to censor certain areas of your screen. The example in this video will show a little boy's face being blurred. This will be demonstrated using Adobe Premiere Pro CS6.
This is used to tweak the memory usage for your computer, it is used for servers more so than workstations but just be careful editing registry settings as it may cause irreversible results. I hold no responsibility for anything you do to the regist…

911 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now