使用套接字从页面加载数据
load data from page with socket
我选择不使用 libcurl,因为我已经花了太多精力尝试让它工作。
所以我是 c++ 的新手,并没有完全理解所有内容。
我无法从示例中获取内容。com/test.php 但使用 test.example.com 确实有效(尽管不得不为其创建一个子域很烦人)
除此之外,有没有办法只获取内容而不获取响应 header?
我的代码:
string result;
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
cout << "WSAStartup failed.\n";
system("pause");
}
SOCKET Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct hostent *host;
host = gethostbyname("www.example.com");
SOCKADDR_IN SockAddr;
SockAddr.sin_port = htons(80);
SockAddr.sin_family = AF_INET;
SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);
cout << "Connecting...\n";
if (connect(Socket, (SOCKADDR*)(&SockAddr), sizeof(SockAddr)) != 0){
cout << "Could not connect";
system("pause");
}
cout << "Connected.\n";
send(Socket, "GET / HTTP/1.1\r\nHost: test.example.nl\r\nConnection: close\r\n\r\n", strlen("GET / HTTP/1.1\r\nHost: test.example.nl\r\nConnection: close\r\n\r\n"), 0);
char buffer[10000];
int nDataLength;
while ((nDataLength = recv(Socket, buffer, 10000, 0)) > 0){
int i = 0;
while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') {
result += buffer[i];
i += 1;
}
}
cout << result;
closesocket(Socket);
WSACleanup();
所以我发现前 160 个字符是 header 相关的。
为了过滤掉 header 我这样做了:
while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') {
if(i > 160) {
result += buffer[i];
i += 1;
}
}
但是如果 header 不一样怎么办?例如,它使用不同的服务器或其他东西。或者更改 php 版本。
Header 我收到回复(以防有人感兴趣)
HTTP/1.1 200 OK
Date: Fri, 13 Feb 2015 20:39:56 GMT
Server: Apache
X-Powered-By: PHP/5.3.29
Content-Length: 4
Connection: close
Content-Type: text/html
每次您发出请求时,header 都会改变。您不能只是假设它是固定数量的字节。您必须解析 header。你需要的在这里:
https://www.ietf.org/rfc/rfc2616.txt
如果您查看第 39 页,您会看到 HTTP header 以空行结尾,因此请查找该空行,然后内容在该空行下方。当然,如果这不仅仅是学术练习,您可能会希望找到一个可以为您做这件事的图书馆。 HTTP 相当复杂。
6 响应
在接收并解释请求消息后,服务器响应
带有 HTTP 响应消息。
这是规范的摘录。你想要 "message-body"
Response = Status-Line ; Section 6.1
*(( general-header ; Section 4.5
| response-header ; Section 6.2
| entity-header ) CRLF) ; Section 7.1
CRLF
[ message-body ] ; Section 7.2
我选择不使用 libcurl,因为我已经花了太多精力尝试让它工作。
所以我是 c++ 的新手,并没有完全理解所有内容。
我无法从示例中获取内容。com/test.php 但使用 test.example.com 确实有效(尽管不得不为其创建一个子域很烦人)
除此之外,有没有办法只获取内容而不获取响应 header?
我的代码:
string result;
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
cout << "WSAStartup failed.\n";
system("pause");
}
SOCKET Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct hostent *host;
host = gethostbyname("www.example.com");
SOCKADDR_IN SockAddr;
SockAddr.sin_port = htons(80);
SockAddr.sin_family = AF_INET;
SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);
cout << "Connecting...\n";
if (connect(Socket, (SOCKADDR*)(&SockAddr), sizeof(SockAddr)) != 0){
cout << "Could not connect";
system("pause");
}
cout << "Connected.\n";
send(Socket, "GET / HTTP/1.1\r\nHost: test.example.nl\r\nConnection: close\r\n\r\n", strlen("GET / HTTP/1.1\r\nHost: test.example.nl\r\nConnection: close\r\n\r\n"), 0);
char buffer[10000];
int nDataLength;
while ((nDataLength = recv(Socket, buffer, 10000, 0)) > 0){
int i = 0;
while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') {
result += buffer[i];
i += 1;
}
}
cout << result;
closesocket(Socket);
WSACleanup();
所以我发现前 160 个字符是 header 相关的。 为了过滤掉 header 我这样做了:
while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') {
if(i > 160) {
result += buffer[i];
i += 1;
}
}
但是如果 header 不一样怎么办?例如,它使用不同的服务器或其他东西。或者更改 php 版本。
Header 我收到回复(以防有人感兴趣)
HTTP/1.1 200 OK
Date: Fri, 13 Feb 2015 20:39:56 GMT
Server: Apache
X-Powered-By: PHP/5.3.29
Content-Length: 4
Connection: close
Content-Type: text/html
每次您发出请求时,header 都会改变。您不能只是假设它是固定数量的字节。您必须解析 header。你需要的在这里:
https://www.ietf.org/rfc/rfc2616.txt
如果您查看第 39 页,您会看到 HTTP header 以空行结尾,因此请查找该空行,然后内容在该空行下方。当然,如果这不仅仅是学术练习,您可能会希望找到一个可以为您做这件事的图书馆。 HTTP 相当复杂。
6 响应
在接收并解释请求消息后,服务器响应 带有 HTTP 响应消息。
这是规范的摘录。你想要 "message-body"
Response = Status-Line ; Section 6.1
*(( general-header ; Section 4.5
| response-header ; Section 6.2
| entity-header ) CRLF) ; Section 7.1
CRLF
[ message-body ] ; Section 7.2