【发布时间】:2017-08-21 03:17:02
【问题描述】:
此代码使用 keep-alive 连接以加载许多共享相同 IP 地址的域,但在前 25 个域之后有一个错误,即每次域加载延迟 30 秒!如何解决?
#pragma comment(lib,"ws2_32.lib")
#include <WinSock2.h>
#include <iostream>
int main(){
WSAData wsaData;
WORD DllVersion = MAKEWORD(2, 1);
if (WSAStartup(DllVersion, &wsaData) != 0) {
MessageBoxA(NULL, "Winsock startup failed", "Error", MB_OK | MB_ICONERROR);
exit(1);
}
SOCKADDR_IN addr;
int sizeofaddr = sizeof(addr);
addr.sin_addr.s_addr = inet_addr("123.123.123.123");
addr.sin_port = htons(80);
addr.sin_family = AF_INET;
SOCKET Connection = socket(AF_INET, SOCK_STREAM, NULL);
if (connect(Connection, (SOCKADDR*)&addr, sizeofaddr) != 0)
{
MessageBoxA(NULL, "Failed to Connect", "Error", MB_OK | MB_ICONERROR);
return 0;
}
std::cout << "Connected!" << std::endl;
char MTD[] = "GET / HTTP/1.1\r\nHost:site.com\r\nConnection:keep-alive\r\n\r\nGET / HTTP/1.1\r\nHost:site.com\r\nConnection:keep-alive\r\n\r\nGET / HTTP/1.1\r\nHost:site.com\r\nConnection:keep-alive\r\n\r\nGET / HTTP/1.1\r\nHost:site.com\r\nConnection:keep-alive\r\n\r\nGET / HTTP/1.1\r\nHost:site.com\r\nConnection:keep-alive\r\n\r\nGET / HTTP/1.1\r\nHost:site.com\r\nConnection:keep-alive\r\n\r\nGET / HTTP/1.1\r\nHost:site.com\r\nConnection:keep-alive\r\n\r\nGET / HTTP/1.1\r\nHost:site.com\r\nConnection:keep-alive\r\n\r\nGET / HTTP/1.1\r\nHost:site.com\r\nConnection:keep-alive\r\n\r\nGET / HTTP/1.1\r\nHost:site.com\r\nConnection:close\r\n\r\n";
send(Connection, MTD, sizeof(MTD), NULL);
char MOTD[1];
int result;
while ((result = recv(Connection, MOTD, 1, NULL)) > 0){
std::cout << MOTD[0]; // ...
}
if (result == 0) {
// end of stream
std::cout << "end of stream";
close(Connection);
} else if (result < 0) {
// error
std::cout << "error";
perror("recv"); // at least
close(Connection);
} else {
std::cout << "data received";
// data received, in MOTD[0..result-1]
}
};
【问题讨论】:
-
您的代码中有一个更大的错误:您有一个大小为零的数组,并要求
recv向其中写入一个字节,从而溢出并具有未定义的行为 . -
接收数据的循环中还有一个错误,即您没有检查失败。请记住,
recv在连接关闭时返回0,但在出现错误时返回SOCKET_ERROR(通常为-1)。在 C++ 中,所有非零值都被认为是“真”,因此即使您遇到不可恢复的故障,您仍然会继续进行,就好像什么都没发生一样。而且一次读取一个字节的循环确实是无效的。 -
HTTP 中的行终止符定义为
\r\n,而不是\n。 -
@Someprogrammerdude:所有基于 BSD/POSIX 的套接字 API 实现,包括 WinSock,在套接字函数错误时返回 -1。 Windows 恰好有一个额外的
SOCKET_ERROR常量,该常量定义为 -1 以提高代码可读性。
标签: c++ sockets keep-alive