Client HTTP avec Winsock

Résolu
Utilisateur anonyme - 29 nov. 2008 à 17:45
 Utilisateur anonyme - 2 déc. 2008 à 23:51
Salut à tous,

Je suis entrain de faire un downloader : Comme tout le monde n'a pas la meme version d'indy; je fais ma propre classe en utilisant winsock.

Manque de bol ca ne fonctionne pas : donc je fais appel à des testeurs pour savoir si c'est mon code ou un autre probleme  qui fait des siennes.

Sur une form il faut 2 boutons et 2 Edits.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, WinSock, StdCtrls;

const
  wm_asynch_select= wm_User; 

type
  TForm1 = class(TForm)
    Button1: TButton;
    host_edit_: TEdit;
    Label2: TLabel;
    page_edit_: TEdit;
    Label1: TLabel;
    Button2: TButton;
    procedure Message_Connection(ASocket: Integer);
    procedure Message_Write(ASocket: Integer);
    procedure Message_Read(ASocket: Integer);
    procedure Message_Close(ASocket: Integer);
    procedure Message_wm_async_select(var Msg: TMessage); message wm_asynch_select;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Déclarations privées }
  public
    { Déclarations publiques }
  end;

var
  Form1: TForm1;
 AnWSAData:TWSADATA;
 sock:TSOCKET;
 sin:SOCKADDR_IN;
 AURL:String;
 Command:String;

implementation

{$R *.dfm}

function HostToIP(Name: string; var Ip: string): Boolean;
var
  wsdata : TWSAData;
  hostName : array [0..255] of char;
  hostEnt : PHostEnt;
  addr : PChar;
begin
  WSAStartup ($0101, wsdata);
  try
    gethostname (hostName, sizeof (hostName));
    StrPCopy(hostName, Name);
    hostEnt := gethostbyname (hostName);
    if Assigned (hostEnt) then
      if Assigned (hostEnt^.h_addr_list) then begin
        addr := hostEnt^.h_addr_list^;
        if Assigned (addr) then begin
          IP := Format ('%d.%d.%d.%d', [byte (addr [0]),
          byte (addr [1]), byte (addr [2]), byte (addr [3])]);
          Result := True;
        end
        else
          Result := False;
      end
      else
        Result := False
    else begin
      Result := False;
    end;
  finally
    WSACleanup;
  end
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 If wsaStartup(MAKEWORD(2,0), AnWSAData)<>0 Then Showmessage('Erreur d''initialisation de la dll');

  sock := socket(AF_INET,SOCK_STREAM,0);
  If Sock=INVALID_SOCKET Then Showmessage('ERREUR dans la création du socket');
  HostToIP(host_edit_.Text,AURL);
  sin.sin_addr.s_addr:= inet_addr(PChar(AURL));
  If (sin.sin_addr.s_addr=INADDR_NONE) Or (sin.sin_addr.s_addr=INADDR_ANY) Then
  Showmessage('erreur d''adresse');
  sin.sin_family:= AF_INET;
  sin.sin_port:= htons(80);
  bind(sock, sin, sizeof(sin));
  if Winsock.Connect(sock, sin, SizeOf(sin)) = Socket_Error then
   Showmessage('erreur de connection');
  If wsaAsyncSelect(sock, Handle,wm_asynch_select,FD_CONNECT+ FD_READ+ FD_WRITE+ FD_CLOSE)<>0 Then  
  ShowMessage('Erreur pour asynchrone');
end;

procedure TForm1.Message_Connection(ASocket: Integer);
Begin
  Showmessage('Votre socket '+IntToStr(ASocket)+' est connecté');
  // permet d'être notifié de l'ouverture d'une connection
End;

procedure TForm1.Message_Write(ASocket: Integer);
Begin
//  FD_WRITE : permet d'être notifié lorsque le socket peut être écrit
End;

procedure TForm1.Message_Read(ASocket: Integer);
Var
  Buff:array[0..2047] of Char;
Begin
  Recv(Sock,Buff,SizeOF(Buff),0);
  Showmessage(Buff);
//    FD_READ : permet d'être notifié de la présence de données dans le tampon de lecture associé au socket
End;

procedure TForm1.Message_Close(ASocket: Integer);
Begin
Showmessage('fermée');
// permet d'être notifié de la fermeture d'une connexion.
End;

procedure TForm1.Message_wm_async_select(var Msg: TMessage);
var
  Param: Integer;
  Notif: Integer;
  Socket: Integer;
Begin
  Param:=Msg.LParam;
  Socket:=Msg.WParam;
  Notif:= wsaGetSelectEvent(Param);
  If wsaGetSelectError(Param)<=wsaBaseErr Then
  Case Notif of
    FD_CONNECT: Message_Connection(Socket);
    FD_WRITE: Message_Write(Socket);
    FD_READ: Message_Read(Socket);
    FD_CLOSE: Message_Close(Socket);
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Command:='GET '+ page_edit_.Text+ ' HTTP/1.0'+#1310
  + 'Host: '+ host_edit_.Text+#1310+#1310;
  If Send(sock,Command,SizeOf(Command),0)=SOCKET_ERROR Then Showmessage('Erreur dans la requette');
end;

end.

Pouvez vous me dire ce que vous récupérez comme texte ?

Merci

12 réponses

cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
30 nov. 2008 à 12:21
salut Francky,
j'ai récupéré ton code et ça compile nickel mais il faudrait pour le test soit correct que tu précises les infos à taper dans les deux edits.

cantador
3
Utilisateur anonyme
30 nov. 2008 à 14:28
Bon j'ai trouvé la solution

C'était un simple problème de Pointer

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, WinSock, StdCtrls;

const
  wm_asynch_select= wm_User;

type
  TForm1 = class(TForm)
    Button1: TButton;
    host_edit_: TEdit;
    page_edit_: TEdit;
    Button2: TButton;
    procedure Message_Connection(ASocket: Integer);
    procedure Message_Write(ASocket: Integer);
    procedure Message_Read(ASocket: Integer);
    procedure Message_Close(ASocket: Integer);
    procedure Message_wm_async_select(var Msg: TMessage); message wm_asynch_select;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Déclarations privées }
  public
    { Déclarations publiques }
  end;

var
  Form1: TForm1;
 AnWSAData:TWSADATA;
 sock:TSOCKET;
 sin:SOCKADDR_IN;
 AURL:String;
 Command:String;

implementation

{$R *.dfm}

function HostToIP(Name: string; var Ip: string): Boolean;
var
  wsdata : TWSAData;
  hostName : array [0..255] of char;
  hostEnt : PHostEnt;
  addr : PChar;
begin
  WSAStartup ($0101, wsdata);
  try
    gethostname (hostName, sizeof (hostName));
    StrPCopy(hostName, Name);
    hostEnt := gethostbyname (hostName);
    if Assigned (hostEnt) then
      if Assigned (hostEnt^.h_addr_list) then begin
        addr := hostEnt^.h_addr_list^;
        if Assigned (addr) then begin
          IP := Format ('%d.%d.%d.%d', [byte (addr [0]),
          byte (addr [1]), byte (addr [2]), byte (addr [3])]);
          Result := True;
        end
        else
          Result := False;
      end
      else
        Result := False
    else begin
      Result := False;
    end;
  finally
    WSACleanup;
  end
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 If wsaStartup(MAKEWORD(2,0), AnWSAData)<>0 Then Showmessage('Erreur d''initialisation de la dll');

  sock := socket(AF_INET,SOCK_STREAM,0);
  If Sock=INVALID_SOCKET Then Showmessage('ERREUR dans la création du socket');
  HostToIP(host_edit_.Text,AURL);
  sin.sin_addr.s_addr:= inet_addr(PChar(AURL));
  If (sin.sin_addr.s_addr=INADDR_NONE) Or (sin.sin_addr.s_addr=INADDR_ANY) Then
  Showmessage('erreur d''adresse');
  sin.sin_family:= AF_INET;
  sin.sin_port:= htons(80);
  bind(sock, sin, sizeof(sin));
  if Winsock.Connect(sock, sin, SizeOf(sin)) = Socket_Error then
   Showmessage('erreur de connection');
  If wsaAsyncSelect(sock, Handle,wm_asynch_select,FD_CONNECT+ FD_READ+ FD_WRITE+ FD_CLOSE)<>0 Then 
  ShowMessage('Erreur pour asynchrone');
end;

procedure TForm1.Message_Connection(ASocket: Integer);
Begin
  Showmessage('Votre socket '+IntToStr(ASocket)+' est connecté');
  // permet d'être notifié de l'ouverture d'une connection
End;

procedure TForm1.Message_Write(ASocket: Integer);
Begin
//  FD_WRITE : permet d'être notifié lorsque le socket peut être écrit
End;

procedure TForm1.Message_Read(ASocket: Integer);
Var
  Buff:Array [0..1023] Of Char;
Begin
  Recv(Sock,Buff[0],SizeOf(Buff),0);
  Showmessage(Buff);
//    FD_READ : permet d'être notifié de la présence de données dans le tampon de lecture associé au socket
End;

procedure TForm1.Message_Close(ASocket: Integer);
Begin
Showmessage('fermée');
// permet d'être notifié de la fermeture d'une connexion.
End;

procedure TForm1.Message_wm_async_select(var Msg: TMessage);
var
  Param: Integer;
  Notif: Integer;
  Socket: Integer;
Begin
  Param:=Msg.LParam;
  Socket:=Msg.WParam;
  Notif:= wsaGetSelectEvent(Param);
  If wsaGetSelectError(Param)<=wsaBaseErr Then
  Case Notif of
    FD_CONNECT: Message_Connection(Socket);
    FD_WRITE: Message_Write(Socket);
    FD_READ: Message_Read(Socket);
    FD_CLOSE: Message_Close(Socket);
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Command:='GET http://www.google.com/intl/fr/about.html HTTP/1.0'#13#10 +
                 'Host: www.google.com'#13#10 +
                 'Accept: text/plain'#13#10 +
                 'Accept-Language: en'#13#10 +
                 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.1.16) Gecko/20080702 Firefox/2.0.0.16'#13#10 +
                 'Keep-Alive: 300'#13#10 +
                 'Connection: Keep-Alive'#13#10
                 + #13#10;
  If Send(sock,Pointer(Command)^,Length(Command),0)=SOCKET_ERROR Then Showmessage('Erreur dans la requette');
end;

end.

Je suis tombé sur un thread qui m'a un peu aidé : http://www.developpez.net/forums/d604022/environnements-developpement/delphi/api-com-sdks/winsock-recv-ne-recoit-rien/

Merci Cantador du coup de main
3
Utilisateur anonyme
30 nov. 2008 à 12:48
Salut Cantador

Pour l'édit Host tu peux taper  www.iprelax.fr et pour l'édit de l'adresse tu peux rentrer  /http/

Merci
0
cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
30 nov. 2008 à 13:52
il ne se passe rien sur les deux clics : aucun message.

cantador
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Utilisateur anonyme
30 nov. 2008 à 13:56
Merci Cantador : je pense que l'erreur vients de la requette mais je ne vois pas d'ou elle vient
0
cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
30 nov. 2008 à 14:00
Qu'est ce que tu souhaitais obtenir sur les deux clics ?

cantador
0
Utilisateur anonyme
30 nov. 2008 à 14:04
Je fais une requette HTTP pour récupérer la page de www.iprelax.fr/http/. Je pensais que le probleme venait de mon FAI (Utilisation d'un proxy). Je vais faire un serveur avec TSocket pour comprendre ce qui ne va pas

Merci
0
cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
30 nov. 2008 à 16:33
de rien Francky..

cantador
0
cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
1 déc. 2008 à 20:55
as-tu testé la méthode de Paul Toth ?

cantador
0
Utilisateur anonyme
1 déc. 2008 à 21:57
Je viens de regarder sur google et je n'ai pas trouvé de lien sur le sujet .

Par contre j'hésite entre une classe et un composant : A ton avis lequel est le mieux sachant que c'est juste une option d'un code qui n'a rien avoir?

Merci Cantador
0
cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
2 déc. 2008 à 14:51
Je viens de regarder sur google et je n'ai pas trouvé de lien sur le sujet

le lien est dans le post que tu as fourni...

et je pense que ça vaut le coup de la tester car Toth c'est un bon..

cantador
0
Utilisateur anonyme
2 déc. 2008 à 23:51
J'avais pas vu le lien : Oui le Paul semble etre plutot une pointure . Par contre lui il utilise des sockets bloquants : Ca m'embete d'utiliser des threads pour cela  .
0
Rejoignez-nous