Delphi Winsock 1.1 GET

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by Sams, 21 Nov 2009.

  1. Sams

    Sams Member

    Joined:
    18 Apr 2009
    Messages:
    247
    Likes Received:
    70
    Reputations:
    17
    Всем добрый вечер. Работаю с winsock на делфи. Пытаюсь отправить GET запрос на хост, получить ответ и записать его в компонент Memo. Но к сожалению когда доходит очередь до функции recv() - программа просто зависает. В чем моя ошибка? Буду рад любым советам/ответам по теме. Заранее благодарен.

    P.S. Ответ:"Пиши на АСМ" можете оставить при себе...

    P.P.S. Может это из-за того, что буфер для отправки имеет тип string с максимальным размером в 255 символов, а GET занимает больше, в следствии чего передается не полный запрос, на который не приходит ответ? И что тогда лучше использовать для буфера, TStringStream? А Pchar покатит?
     
    #1 Sams, 21 Nov 2009
    Last edited: 21 Nov 2009
  2. ntldr

    ntldr Elder - Старейшина

    Joined:
    4 Dec 2007
    Messages:
    367
    Likes Received:
    140
    Reputations:
    23
    для буфера не используют string. Лучше pchar а лучше массив из byte.
    А самый правильный ответ - запусти программу под отладчиком, и посмотри что происходит в этом месте
     
    1 person likes this.
  3. Sams

    Sams Member

    Joined:
    18 Apr 2009
    Messages:
    247
    Likes Received:
    70
    Reputations:
    17
    Попробовал через PChar. К сожалению результат тот же. Зависает.
     
  4. wolmer

    wolmer Member

    Joined:
    12 May 2009
    Messages:
    438
    Likes Received:
    97
    Reputations:
    9
    Так правильней (писал тут, должно работать):
    Code:
    unit Unit1;
    
    interface
    
    uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    Dialogs, winsock, StdCtrls;
    
    type
    TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Button1Click(Sender: TObject);
    private
    { Private declarations }
    public
    { Public declarations }
    end;
    
    var
    Form1: TForm1;
    info: WSADATA;
    sin: sockaddr_in;
    myip: PHostEnt;
    sHwnd: integer;
    sBuff1:string;
    sBuff, rBuff: array [0..5000] of char;
    
    implementation
    
    {$R *.dfm}
    
    procedure TForm1.FormCreate(Sender: TObject);
    begin
    WSAStartup(makeword(1,1),info);
    sHwnd:=Socket(AF_INET, SOCK_STREAM, 0);
    sin.sin_family:=AF_INET;
    sin.sin_port:=htons(80);
    sin.sin_addr.S_addr:=inet_addr('77.221.159.154');
    connect(sHwnd, sin, sizeof(sin));
    sbuff1:='GET /article.php?article=1016003 HTTP/1.1' + #13#10 +
    'User-Agent: ManualSender/1.0' + #13#10 +
    'Host: www.wasm.ru' + #13#10 +
    #13#10;
    CopyMemory(@sBuff,pchar(sBuff1),length(sBuff1));
    end;
    
    procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
    Closesocket(sHwnd);
    WSACleanup;
    end;
    
    procedure TForm1.Button1Click(Sender: TObject);
    begin
    send(sHwnd, sBuff, Length(sBuff), 0);
    recv(sHwnd, rBuff, Length(rBuff), 0);
    Memo1.Lines.Add(rBuff);
    end;
    
    end.
     
    1 person likes this.
  5. Sams

    Sams Member

    Joined:
    18 Apr 2009
    Messages:
    247
    Likes Received:
    70
    Reputations:
    17
    ntldr, спасибо за совет.
    wolmer, спасибо! Твой вариант работает. Данные нормально принимает и ничего не виснет. Woohoo :) Благодарю еще раз :)
     
  6. Sams

    Sams Member

    Joined:
    18 Apr 2009
    Messages:
    247
    Likes Received:
    70
    Reputations:
    17
    А еще такой вопрос. Что бы получить данные, нужно знать IP:
    А каким образом тогда можно реализовать что-то на подобие IdHTTP. Тоесть поле Edit, Button и Memo. Вводишь в Edit ссылку сайта, жмешь на button и результат выводится в Memo. Вся суть в том, как узнать IP, что б подставить в структуру sockaddr_in?
     
    #6 Sams, 21 Nov 2009
    Last edited: 21 Nov 2009
  7. wolmer

    wolmer Member

    Joined:
    12 May 2009
    Messages:
    438
    Likes Received:
    97
    Reputations:
    9
    Code:
    function TForm1.hosttoip(name: string): string;
    var
     wsdata  :twsadata;
     hostname:array [0..255] of char;
     hostent :phostent;
     addr    :pchar;
     ip      :string;
    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 := ip;
             end
            else
               result:='';
          end
         else
            result := ''
       else
        begin
          result := '';
        end;
     finally
       wsacleanup;
     end
    end;
    (сразу говорю, код не мой, взят с сети)

    Пример:
    sin.sin_addr.S_addr:=inet_addr(pchar(hosttoip('yandex.ru')));
    {На счет преобр в pchar не уверен. Yandex если что пишется вместе (баг форума)}
     
    #7 wolmer, 21 Nov 2009
    Last edited: 21 Nov 2009
  8. Sams

    Sams Member

    Joined:
    18 Apr 2009
    Messages:
    247
    Likes Received:
    70
    Reputations:
    17
    Спасибо. Работает. Перепроверил айпи через трассировку :)

    P.S.
    Как раз только через PChar и работает :)
     
    #8 Sams, 21 Nov 2009
    Last edited: 22 Nov 2009
  9. zer0ska

    zer0ska Elder - Старейшина

    Joined:
    5 Dec 2007
    Messages:
    103
    Likes Received:
    9
    Reputations:
    0
    покажите на примере етого кода как отрезать зоголовки от ответа чтоб получить голы хтмл
     
  10. wolmer

    wolmer Member

    Joined:
    12 May 2009
    Messages:
    438
    Likes Received:
    97
    Reputations:
    9
    Code:
    memo1.lines.text:=copy(memo1.lines.text, pos(#13#10#13#10, memo1.lines.text)+4, length(memo1.lines.text)-pos(#13#10#13#10, memo1.lines.text));