在 C++ 中的 Winsock 中发送 HTTP GET 请求后,Recv() 函数挂起
Posted
技术标签:
【中文标题】在 C++ 中的 Winsock 中发送 HTTP GET 请求后,Recv() 函数挂起【英文标题】:Recv() Function Hangs After Sending HTTP GET Request in Winsock in C++ 【发布时间】:2013-03-25 07:18:47 【问题描述】:我正在尝试在 winsock 中创建一个使用 HTTP 的程序,但我遇到了一个问题,recv 函数只是挂在那里。
int connect()
WSADATA t_wsa; //WSADATA structure
WORD wVers = 0x0202; //version number
int iError; //error number
wVers = MAKEWORD(2, 2); // Set the version number to 2.2
iError = WSAStartup(wVers, &t_wsa); // Start the WSADATA
if(iError != NO_ERROR || iError == 1)
printf("Error at WSAStartup()\n");
WSACleanup();
system("PAUSE");
return 1;
/* Correct version? */
if(LOBYTE(t_wsa.wVersion) != 2 || HIBYTE(t_wsa.wVersion) != 2)
printf("Incorrect version\n");
WSACleanup();
system("PAUSE");
return 1;
SOCKET sClient;
sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sClient == INVALID_SOCKET || iError == 1)
printf("Invalid Socket!\n");
WSACleanup();
system("PAUSE");
return 1;
SOCKADDR_IN sinClient;
memset(&sinClient, 0, sizeof(sinClient));
char cIP[50];
strcpy_s(cIP, "98.139.183.24");
sinClient.sin_family = AF_INET;
sinClient.sin_addr.s_addr = inet_addr(cIP); // Where to start server
sinClient.sin_port = htons(80); //Port
if(connect(sClient, (LPSOCKADDR)&sinClient, sizeof(sinClient)) == SOCKET_ERROR)
/* failed at starting server */
printf("Could not connect ot the server!\n");
WSACleanup();
system("PAUSE");
return 1;
// Now we can send/recv data!
printf("YOU ARE CONNECTED!\r\n");
string buffer;
buffer += "GET / HTTP/1.1\r\n";
buffer += "Host: http://www.yahoo.com/\r\n";
buffer += "Connection: close\r\n\r\n";
const char *cha = buffer.c_str();
int sent;
int response;
sent = send(sClient, cha, sizeof(cha) - 1, 0);
char recvbuf[50000];
response = recv(sClient, recvbuf, 50000, 0);
recvbuf[response] = '\0';
printf("\nReceived data = %s", recvbuf);
WSACleanup();
return(0);
"sent" 将在 send 函数后打印,但在 recv 后什么也不打印。
我在这里错过了什么?
【问题讨论】:
【参考方案1】:一个可能的原因是send()
没有发送预期的数据:
sent = send(sClient, cha, sizeof(cha) - 1, 0);
sizeof(cha) - 1
实际上是sizeof(char*) - 1
,而不是数据的实际长度:请改用buffer.length()
。
请注意,您可以在单个语句中使用字符串文字构造std::string
,而不是通过多个连接来构造它。但是,由于 std::string
仅用于获取 const char*
,因此根本没有理由使用 std::string
:
const char* buffer = "GET / HTTP/1.1\r\n"
"Host: http://www.yahoo.com/\r\n"
"Connection: close\r\n\r\n";
sent = send(sClient, buffer, strlen(buffer), 0);
检查send()
和recv()
的返回值以确定成功或失败,尤其是recv()
,因为结果用于索引数组。失败时,recv()
返回SOCKET_ERROR
(我认为)是-1
。
正确处理 HTTP 响应需要付出很大的努力。接收代码需要检查返回的HTTP headers,以确定如何处理响应内容。例如,HTTP 响应可能被分块或不分块。存在用于管理 HTTP 请求的库,一个是 cpp-netlib(大约在 2013 年 2 月在 isocpp.org 上宣布)。
【讨论】:
由于代码使用的是 WinSock,它在 Windows 上运行,因此可以使用 Microsoft 的 WinInet 或 WinHTTP API 作为直接使用 WinSock 的替代方案。 我在linux环境中使用该函数时遇到了同样的问题。我使用了 sizeof ,它使 recv 函数可以处理。现在我正在使用 strlen,它按预期工作。以上是关于在 C++ 中的 Winsock 中发送 HTTP GET 请求后,Recv() 函数挂起的主要内容,如果未能解决你的问题,请参考以下文章