0

winsock 2 を使用して C++ で HTTP リクエストを実装しようとしています。

http://stackoverflow.comに接続した後、送信するものは次のとおりです。

send(_socket, "GET / HTTP/1.1\r\nHost: www.stackoverflow.com\r\n\r\n", (the length ), 0);

そして今、応答を読んでいます:

std::string s;
char buffer[BUFFER_LENGTH];
int bytes = 0;

do
{
    ZeroMemory(buffer, BUFFER_LENGTH);
    bytes = recv(_socket, buffer, BUFFER_LENGTH, 0);
    s.append(buffer);
} while (bytes == BUFFER_LENGTH);

return s;

ところで:#define BUFFER_LENGTH 512

ここに奇妙な部分があります。プログラムを実行すると、応答のヘッダー部分のみが取得されます。

HTTP/1.1 200 OK

Cache-Control: public, max-age=34

Content-Type: text/html; charset=utf-8

Expires: Wed, 04 Sep 2013 08:14:00 GMT

Last-Modified: Wed, 04 Sep 2013 08:13:00 GMT

Vary: *

X-Frame-Options: SAMEORIGIN

Date: Wed, 04 Sep 2013 08:13:26 GMT

Content-Length: 193288

しかし、読み取り関数を段階的にデバッグすると、コンテンツを含むすべての応答が得られます。ZeroMemory() 関数にブレークポイントを設定し、一度に 1 つの「コマンド」を進める F10 キー (ステップ オーバー) を押してコードを実行し続けると、ループが数回続き、完全な応答が返されます。 、ヘッダーとコンテンツの両方。しかし、recv() 関数 (s.append(buffer)) の後にブレークポイントを置くと、ループはすぐに (ループを 1 回だけ実行した後) 存在し、ヘッダーだけを再実行します。

誰かが私にこの振る舞いを説明できますか?

私が想定しているのは、ヘッダーとコンテンツの送信の間に何らかの時間遅延があるため、デバッガーで recv() の前に停止すると、サーバーはそれを送信するのに十分な時間があるため、recv() はそれを読み取ることができますすべてですが、後に置くと、サーバーはヘッダーを送信するのに十分な時間しかなく、recv() 関数は既に到着したものだけを読み取り、512 バイト未満の読み取りを返し、ループが存在します。私は正しいですか?

前もって感謝します!

4

1 に答える 1

0

コメントで述べたように、データがまだ到着していない場合、バッファサイズよりも小さくなる可能性があるという仮定は正しいです。ループで行うべきことは、実際に HTTP の知識を使用することです。たとえば\r\n\r\n、ヘッダーがいつ到着したかを調べてから、コンテンツの長さを調べて、コンテンツのその量のデータを読み取ろうとします。あるいは、すでにWinsock2彼らのメソッドHttpSendRequest( http://msdn.microsoft.com/en-us/library/windows/desktop/aa384247(v=vs.85).aspx ) と友人を使用しているため、すべての問題が少なくなります。やりたいことは、リクエストを送信することだけです。

于 2013-09-04T08:50:41.610 に答える