使用gethostbyname访问违规之谜?

时间:2013-03-12 04:59:59

标签: c++

std::cout << WebClient().Load(in.substr(2, in.length()));

我制作了一个很有趣的WebClient,你可以通过cin传入一个字符串到via std :: getline(cin,in);

我的Load方法的开始部分:

std::string Load(std::string url)
{
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
        return "WSAStartup failed.\n";
    }
    SOCKET Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    struct hostent *host;
    host = gethostbyname(url.c_str());
    SOCKADDR_IN SockAddr;
    SockAddr.sin_port=htons(80);
    SockAddr.sin_family=AF_INET;
    if(host != nullptr)
    {
        SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);
    }

我会得到一个访问冲突,因为主机变成了一个nullptr(因此检查它),但是使用相同的字符串,但以不同的方式传递:WebClient()。加载(“www.google.ca”)它的工作原理。我尝试将c_str()放在substr'ed字符串的末尾但没有用。

我还在学习怪癖,这是怎么回事?我正在使用

中的标准库
#include <http.h>
#include <string>
#include <winsock2.h>
#include <windows.h>
#include <iostream>
#pragma comment(lib,"ws2_32.lib")

2 个答案:

答案 0 :(得分:3)

尝试检查从getline收到的传入字符串的值。 gethostbyname收到它时可能会出错。您可以使用WSAGetLastError检查它是否失败(并变为NULL)。查看MSDN以查找gethostbyname可能的error codes

编辑:您说您的参数看似相同。你能找到一种方法证明这一点(对你自己)。也许那里有无形的角色?新行\n,或者它可能使用不同的编码?只是一些想法。

答案 1 :(得分:2)

编写我的评论作为答案:您应该以一种方式打印URL,以便查看是否有额外的字符,甚至是空格。然后你应该检查你使用的所有函数的错误代码,比如这里阅读the documentation of gethostbyname。下面是您的函数的调试版本,您需要error codes explained here

#include <cstring>

std::string Load(std::string url)
{
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
        return "WSAStartup failed.\n";
    }
    SOCKET Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    struct hostent *host;
    std::cout << "Getting hostname for url as seen by gethostbyname: '" << url.c_str() << "', strlen=" << strlen(url.c_str()) << std::endl;
    host = gethostbyname(url.c_str());
    if (host) {
        std::cout << "got valid hostent as response" << std::endl;
    } else {
        std::cout << "gethostbyname WSAGetLastError=" << WSAGetLastError() << std::endl;
        return "Invalid url.\n";
    }
    SOCKADDR_IN SockAddr;
    SockAddr.sin_port=htons(80);
    SockAddr.sin_family=AF_INET;
    if(host != nullptr)
    {
        SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);
    }

猜测原因:来自cin的您的网址中有空格。

关于术语的说明:该地址字符串,它不是真正的url,url必须在开始时具有类似http://的方案。您所拥有的是主机的完全限定域名,因为它也应该是gethostbyname不理解网址。