Client HTTP avec Winsock [Résolu]

Utilisateur anonyme - 29 nov. 2008 à 17:45 - Dernière réponse :  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
Afficher la suite 

Votre réponse

12 réponses

cs_cantador 4996 Messages postés dimanche 26 février 2006Date d'inscription 27 mars 2018 Dernière intervention - 30 nov. 2008 à 12:21
+3
Utile
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
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de cs_cantador
Utilisateur anonyme - 30 nov. 2008 à 14:28
+3
Utile
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
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de Utilisateur anonyme
Utilisateur anonyme - 30 nov. 2008 à 12:48
0
Utile
Salut Cantador

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

Merci
Commenter la réponse de Utilisateur anonyme
cs_cantador 4996 Messages postés dimanche 26 février 2006Date d'inscription 27 mars 2018 Dernière intervention - 30 nov. 2008 à 13:52
0
Utile
il ne se passe rien sur les deux clics : aucun message.

cantador
Commenter la réponse de cs_cantador
Utilisateur anonyme - 30 nov. 2008 à 13:56
0
Utile
Merci Cantador : je pense que l'erreur vients de la requette mais je ne vois pas d'ou elle vient
Commenter la réponse de Utilisateur anonyme
cs_cantador 4996 Messages postés dimanche 26 février 2006Date d'inscription 27 mars 2018 Dernière intervention - 30 nov. 2008 à 14:00
0
Utile
Qu'est ce que tu souhaitais obtenir sur les deux clics ?

cantador
Commenter la réponse de cs_cantador
Utilisateur anonyme - 30 nov. 2008 à 14:04
0
Utile
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
Commenter la réponse de Utilisateur anonyme
cs_cantador 4996 Messages postés dimanche 26 février 2006Date d'inscription 27 mars 2018 Dernière intervention - 30 nov. 2008 à 16:33
0
Utile
de rien Francky..

cantador
Commenter la réponse de cs_cantador
cs_cantador 4996 Messages postés dimanche 26 février 2006Date d'inscription 27 mars 2018 Dernière intervention - 1 déc. 2008 à 20:55
0
Utile
as-tu testé la méthode de Paul Toth ?

cantador
Commenter la réponse de cs_cantador
Utilisateur anonyme - 1 déc. 2008 à 21:57
0
Utile
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
Commenter la réponse de Utilisateur anonyme
cs_cantador 4996 Messages postés dimanche 26 février 2006Date d'inscription 27 mars 2018 Dernière intervention - 2 déc. 2008 à 14:51
0
Utile
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
Commenter la réponse de cs_cantador
Utilisateur anonyme - 2 déc. 2008 à 23:51
0
Utile
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  .
Commenter la réponse de Utilisateur anonyme

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.