1

URL リストを取得したので、すべての Web ページを取得したいと考えています。これが私がやったことです:

 for each url:
     getaddrinfo(hostname, port, &hints, &res);         // DNS
     // create socket 
     sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
     connect(sockfd, res->ai_addr, res->ai_addrlen);
     creatGET();
     /* for example:
        GET / HTTP/1.1\r\n
        Host: stackoverflow.cn\r\n
        ...
      */
     writeHead();   // send GET head to host
     recv();        // get the webpage content   
end

多くの URL が同じホストの下にあることに気付きました。たとえば、次のようになります。

 http://job.01hr.com/j/f-6164230.html
 http://job.01hr.com/j/f-6184336.html
 http://www.012yy.com/gangtaiju/32692/
 http://www.012yy.com/gangtaiju/35162/

だから私は、connect各ホストに1回だけcreatGET()、次に各URLwriteHead()に1回だけできますか? recv()それは多くの時間を節約するかもしれません。そこで、プログラムを次のように変更しました。

split url into groups by their host;
for each group:
    get hostname in the group;
    getaddrinfo(hostname, port, &hints, &res);         
    sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    connect(sockfd, res->ai_addr, res->ai_addrlen);
    for each url in the group:        
        creatGET();
        writeHead(); 
        recv();
    end
end

残念ながら、私のプログラムは各グループの最初の Web ページしか取得できず、残りはすべて空のファイルを返すことがわかりました。何か不足していますか?たぶん、各 recv() にsockfd何らかの必要がありますか?reset

あなたの寛大な助けに感謝します。

4

1 に答える 1

2

HTTP 1.1 接続は永続的です。つまり、たとえば POST/GET - 200 OK シーケンスの後、次の要求応答シーケンスで、すでに確立されている TCP 接続を再利用できます。
しかし、これは必須ではありません。接続はいつでも閉じられる可能性があるため、そのためのコードも作成する必要があります。

また、独自の HTTP クライアントを実装しようとしているように思えます。
なぜそうする必要があるのか​​ わかりませんが、HTTP RFCについて少し読んで、さまざまなヘッダーについて理解し、基礎となるTCP接続が可能な限り開いていることを確認する必要があります.

もちろん、サーバーが古い HTTP1.0 の場合、keep-alive ヘッダーで明示的に示されない限り、接続の再利用を期待するべきではありません。

于 2012-04-21T08:16:47.783 に答える