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 中提到的其他问题应该可以帮助您入门。