【问题标题】:C++ Winsock programming, receiving no response from HTTP protocolC++ Winsock编程,没有收到HTTP协议的响应
【发布时间】:2015-08-22 02:12:10
【问题描述】:

正如标题所说,我刚刚开始研究 TCP/IP 协议如何应用于 C++,因此我尝试使用 IP 地址(在本例中为 www.nasa.gov)发送数据包到任何随机网站( DNS Resolver)和一个随机端口(我选择了 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;
}

【问题讨论】:

  • 您缺少所有换行符并在一行中发送数据。它不会工作
  • 如果您正在谈论使用这种东西:"Accept-Language: en-us" "Connection: keep-alive",它确实有效。还是你的意思是每行都要单独发送?
  • 这与“Accept-Language: en-usConnection: keep-alive”相同,这是不正确的。 HTTP 要求 CRLF 在请求结束之间和两个之间
  • Windows 上的 Wireshark 需要一些扩展才能查看本地主机数据包。
  • @user4581301:或者您可以使用自定义 ROUTE 将本地数据包从网络路由器反弹回 localhost,以便 Wireshark 可以正常捕获它们。

标签: c++ sockets http tcp ip


【解决方案1】:

HTTP 协议要求所有标题行都以 CRLF 结尾,并且后面跟一个空行。您的所有标题行都没有任何换行符。

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 次相同的响应字符串,但这并不影响实际的请求。

【讨论】:

  • 200 个字符的上限是为了确保一切都适合,我认为这应该不是问题,但我会尝试让您知道它是否有效
  • 您还需要将GET这一行改为GET /index.html HTTP/1.1\r\n,然后将HTTP请求发送到www.nasa.gov本身的IP地址。使用gethostbyname()getaddrinfo() 获取该IP,不要让用户手动输入。显示的原始 GET 行仅在将 HTTP 请求发送到 HTTP 代理服务器时才有效。
【解决方案2】:

我认为您的代码有问题 - 您正在尝试连接到

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";

这意味着 - 您正在尝试“连接”到端口 80 上的广播地址。我认为您应该收到 Connection Refused 错误。

注意:仅仅有一条线 Host: www.nasa.gov 不足以连接到 www.nasa.gov。您必须首先使用getaddrinfo 行对其进行名称解析。但我建议 - 因为您似乎正在学习 - 一个好主意是在命令行上执行 nslookup(命令提示符 cmd),然后在上面的 ip 中使用返回的 IP。下一步是使用getaddrinfo

检查connect 是否成功并仅在连接成功时执行send 等也是一个好主意。如果 connect 失败 - 一个好主意是打印错误。

这加上 HTTP 标头中提到的其他问题应该可以帮助您入门。

【讨论】:

  • cout &lt;&lt; "Insert an IP to connect to : "; cin &gt;&gt; ip; 所以这不是问题。问题是消息,谢谢你的提示:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-05
  • 1970-01-01
  • 2012-02-15
  • 1970-01-01
  • 1970-01-01
  • 2020-11-05
  • 1970-01-01
相关资源
最近更新 更多