在不关闭连接的情况下接收整个页面

Receive whole page without closing connection

本文关键字:情况下 连接      更新时间:2023-10-16

请不要太重视代码中的小犯规,专注于问题。

代码请求同一页面 10 次。它调用 recv 直到缓冲区的字节为零,以确保我收到所有内容。问题是,当 recv 的字节为零时,它会关闭连接,这意味着我只收到了第一页。在请求下一个页面之前,我需要收到整个页面。

如何接收整个页面并知道这是我最后一次在不转到零字节的情况下调用 recv ?

#include <iostream>
#include <fstream>
#include <winsock2.h>
#include <time.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
int main() {
WSADATA w;
WORD DllVersion = MAKEWORD(2, 1);
WSAStartup(DllVersion, &w);
SOCKADDR_IN u = { AF_INET,htons(80),0,0 };
u.sin_addr.s_addr = inet_addr("1.1.1.1");
SOCKET e = socket(AF_INET, 0, 0);
connect(e, (SOCKADDR*)&u, sizeof(u));
string l="GET / HTTP/1.1rnHost:www.site.comrnConnection:keep-alivernrn";
char b[100000];
int i,iResult,iError,error;
ofstream z("pg.htm");
for(i=0;i<10;i++){
send(e, l.c_str(), strlen(l.c_str()), 0);
do{
clock_t begin = clock();
z << b;
memset(b, 0, sizeof(b));
int iResult=recv(e, b, sizeof(b), 0);
if (iResult == SOCKET_ERROR ) {
int iError = WSAGetLastError();
if (iError == WSAEWOULDBLOCK)
printf("recv failed with error: WSAEWOULDBLOCKn");
else
printf("recv failed with error: %ldn", iError);
}
wchar_t *s=NULL;
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,NULL,WSAGetLastError(),MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),(LPWSTR)&s,0,NULL);
fprintf(stderr,"%Sn",s);
LocalFree(s);
clock_t end = clock();
double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
cout << time_spent;
cout << "#";
cout << iResult;
cout << "#";
}while(strlen(b)!=0);
memset(b, 0, sizeof(b));
}
}

问题很可能是套接字阻塞,所以如果没有什么可读取的,那么recv将无限期阻塞,直到收到某些内容或检测到错误才会返回。

另一方面,当您的程序在recv函数中被阻止时,服务器将超时并关闭连接。这将导致程序中的recv被解锁并返回0

如果要继续使用相同的连接,则需要使套接字不阻塞,并检查recv调用的故障。当recv通常会阻止它时,它会返回错误(SOCKET_ERROR(并将错误代码(从WSAGetLastError获得(设置为WSAEWOULDBLOCK