C++ Winsock编程,没有收到HTTP协议的响应
C++ Winsock programming, receiving no response from HTTP protocol
正如标题所说,我刚刚开始研究 TCP/IP 协议如何应用于 C++,因此我尝试将数据包发送到任何随机网站(在本例中为 www.nasa.gov),使用IP 地址(DNS 解析器)和一个随机端口(我选择了 80),但我没有收到任何答复。我不知道代码是否错误,因为据我所知它是正确的:
如果代码是正确的,是关于使用不同的端口(因为我已经尝试过 0、27 和 80),还是?我也试过向 127.0.0.1 发送一个数据包,这样我就可以很容易地通过 Wireshark 捕获它,但是什么也没有出现。有时,当使用这个程序向随机网站发送数据包时,我会得到一个我无法再次模拟的奇怪答案。
#pragma comment(lib,"Ws2_32.lib")
#include <iostream>
#include <winsock2.h>
#include <windows.h>
#include <string>
#include <fstream>
#define SCK_VERSION2 0x0202
using namespace std;
int main()
{
//File buffer
ofstream buf;
buf.open("message.txt");
//All the important stuff
long SUCCESFUL;
WSAData WinSockData;
WORD DLLVersion;
DLLVersion = MAKEWORD(2,1);
SUCCESFUL = WSAStartup(DLLVersion, &WinSockData);
char ip[] = "255.255.255.255";
short unsigned int port;
cout << "Insert an IP to connect to : ";
cin >> ip;
cout << "\nInsert a port to connect to: ";
cin >> port;
char message[] = "GET http://www.nasa.gov/index.html HTTP/1.1"
"Host: www.nasa.gov"
"Accept: */*"
"Accept-Language: en-us"
"Connection: keep-alive"
"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)";
string RESPONSE,
CONVERTER;
char MESSAGE[200];
SOCKADDR_IN ADDRESS;
SOCKET sock = socket(AF_INET, SOCK_STREAM, NULL);
ADDRESS.sin_addr.s_addr = inet_addr(ip);
ADDRESS.sin_family = AF_INET;
ADDRESS.sin_port = htons(port);
cout << "\nDo You want to connect to " << ip << ":" << port << "? (Y/N)";
cin >> RESPONSE;
RESPONSE[0] = tolower(RESPONSE[0]);
if(RESPONSE[0] == 'n')
cout << "\nNot connecting.";
else if(RESPONSE[0] == 'y')
{
cout << "\nSending...";
connect(sock, (SOCKADDR*)&ADDRESS, sizeof(ADDRESS));
send(sock,message,sizeof(message),NULL);
SUCCESFUL = recv(sock, MESSAGE,sizeof(MESSAGE),NULL);
CONVERTER = MESSAGE;
cout << "\nMessage: " << hex << CONVERTER;
cout << "\nDone.";
}
for(unsigned short int loop = 0; loop < 200; loop++)
buf << CONVERTER;
buf.close();
return 0;
}
HTTP 协议要求所有 header 行都以 CRLF 结尾,后面跟一个空行。你有所有 header 行没有任何换行符。
char message[] = "GET http://www.nasa.gov/index.html HTTP/1.1"
"Host: www.nasa.gov"
"Accept: */*"
"Accept-Language: en-us"
"Connection: keep-alive"
"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)";
这等于
char message[] = "GET http://www.nasa.gov/index.html HTTP/1.1Host: www.nasa.govAccept: */*...
你需要把它们分开
char message[] = "GET /index.html HTTP/1.1\r\n"
"Host: www.nasa.gov\r\n"
"Accept: */*\r\n"
"Accept-Language: en-us\r\n"
"Connection: keep-alive\r\n"
"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)\r\n"
"\r\n";
还要注意最后的两个CRLF。
出于测试目的,我还建议不要使用 keep-alive 以使其更简单。
你还有一个奇怪的循环,最后输出相同的响应字符串 200 次,但这并不影响实际请求。
我认为您的代码有问题 - 您正在尝试连接
ADDRESS.sin_addr.s_addr = inet_addr(ip);
ADDRESS.sin_family = AF_INET;
ADDRESS.sin_port = htons(port);
其中 ip
是
char ip[] = "255.255.255.255";
这意味着 - 你正试图 'connect' 到端口 80 上的广播地址。我认为你应该得到一个 Connection Refused
错误。
注意:仅仅有一条线 Host: www.nasa.gov
不足以连接到 www.nasa.gov。您必须首先使用某行 getaddrinfo
对其进行名称解析。但我建议 - 因为您似乎正在学习 - 一个好主意是在命令行(命令提示符 cmd
)上执行 nslookup
,然后在 ip
中使用返回的 IP ] 多于。下一步是使用 getaddrinfo
。
检查 connect
是否成功并仅在连接成功后执行 send
等也是一个好主意。如果 connect
失败 - 一个好主意是打印错误。
加上 HTTP Header 中提到的其他问题应该可以帮助您入门。
正如标题所说,我刚刚开始研究 TCP/IP 协议如何应用于 C++,因此我尝试将数据包发送到任何随机网站(在本例中为 www.nasa.gov),使用IP 地址(DNS 解析器)和一个随机端口(我选择了 80),但我没有收到任何答复。我不知道代码是否错误,因为据我所知它是正确的: 如果代码是正确的,是关于使用不同的端口(因为我已经尝试过 0、27 和 80),还是?我也试过向 127.0.0.1 发送一个数据包,这样我就可以很容易地通过 Wireshark 捕获它,但是什么也没有出现。有时,当使用这个程序向随机网站发送数据包时,我会得到一个我无法再次模拟的奇怪答案。
#pragma comment(lib,"Ws2_32.lib")
#include <iostream>
#include <winsock2.h>
#include <windows.h>
#include <string>
#include <fstream>
#define SCK_VERSION2 0x0202
using namespace std;
int main()
{
//File buffer
ofstream buf;
buf.open("message.txt");
//All the important stuff
long SUCCESFUL;
WSAData WinSockData;
WORD DLLVersion;
DLLVersion = MAKEWORD(2,1);
SUCCESFUL = WSAStartup(DLLVersion, &WinSockData);
char ip[] = "255.255.255.255";
short unsigned int port;
cout << "Insert an IP to connect to : ";
cin >> ip;
cout << "\nInsert a port to connect to: ";
cin >> port;
char message[] = "GET http://www.nasa.gov/index.html HTTP/1.1"
"Host: www.nasa.gov"
"Accept: */*"
"Accept-Language: en-us"
"Connection: keep-alive"
"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)";
string RESPONSE,
CONVERTER;
char MESSAGE[200];
SOCKADDR_IN ADDRESS;
SOCKET sock = socket(AF_INET, SOCK_STREAM, NULL);
ADDRESS.sin_addr.s_addr = inet_addr(ip);
ADDRESS.sin_family = AF_INET;
ADDRESS.sin_port = htons(port);
cout << "\nDo You want to connect to " << ip << ":" << port << "? (Y/N)";
cin >> RESPONSE;
RESPONSE[0] = tolower(RESPONSE[0]);
if(RESPONSE[0] == 'n')
cout << "\nNot connecting.";
else if(RESPONSE[0] == 'y')
{
cout << "\nSending...";
connect(sock, (SOCKADDR*)&ADDRESS, sizeof(ADDRESS));
send(sock,message,sizeof(message),NULL);
SUCCESFUL = recv(sock, MESSAGE,sizeof(MESSAGE),NULL);
CONVERTER = MESSAGE;
cout << "\nMessage: " << hex << CONVERTER;
cout << "\nDone.";
}
for(unsigned short int loop = 0; loop < 200; loop++)
buf << CONVERTER;
buf.close();
return 0;
}
HTTP 协议要求所有 header 行都以 CRLF 结尾,后面跟一个空行。你有所有 header 行没有任何换行符。
char message[] = "GET http://www.nasa.gov/index.html HTTP/1.1"
"Host: www.nasa.gov"
"Accept: */*"
"Accept-Language: en-us"
"Connection: keep-alive"
"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)";
这等于
char message[] = "GET http://www.nasa.gov/index.html HTTP/1.1Host: www.nasa.govAccept: */*...
你需要把它们分开
char message[] = "GET /index.html HTTP/1.1\r\n"
"Host: www.nasa.gov\r\n"
"Accept: */*\r\n"
"Accept-Language: en-us\r\n"
"Connection: keep-alive\r\n"
"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)\r\n"
"\r\n";
还要注意最后的两个CRLF。
出于测试目的,我还建议不要使用 keep-alive 以使其更简单。
你还有一个奇怪的循环,最后输出相同的响应字符串 200 次,但这并不影响实际请求。
我认为您的代码有问题 - 您正在尝试连接
ADDRESS.sin_addr.s_addr = inet_addr(ip);
ADDRESS.sin_family = AF_INET;
ADDRESS.sin_port = htons(port);
其中 ip
是
char ip[] = "255.255.255.255";
这意味着 - 你正试图 'connect' 到端口 80 上的广播地址。我认为你应该得到一个 Connection Refused
错误。
注意:仅仅有一条线 Host: www.nasa.gov
不足以连接到 www.nasa.gov。您必须首先使用某行 getaddrinfo
对其进行名称解析。但我建议 - 因为您似乎正在学习 - 一个好主意是在命令行(命令提示符 cmd
)上执行 nslookup
,然后在 ip
中使用返回的 IP ] 多于。下一步是使用 getaddrinfo
。
检查 connect
是否成功并仅在连接成功后执行 send
等也是一个好主意。如果 connect
失败 - 一个好主意是打印错误。
加上 HTTP Header 中提到的其他问题应该可以帮助您入门。