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

I made a WebClient for fun, and you can pass in a string through cin to in via std::getline(cin, in);

The starting part of my Load method:

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);
    }

I would get an Access Violation because host becomes a nullptr (hence checking it), yet with the same string but passed in differently: WebClient().Load("www.google.ca") it works. and I tried putting c_str() at the end of the substr'ed string with no avail.

I am still learning the quirks, what's up with this? I am using standard libraries from

#include <http.h>
#include <string>
#include <winsock2.h>
#include <windows.h>
#include <iostream>
#pragma comment(lib,"ws2_32.lib")
4

2 回答 2

2

Try checking what the value of the passed in string is received as from getline. It could be malformed when gethostbyname receives it. You can check if this is where it's failing (and becoming NULL) by using WSAGetLastError. Check MSDN for gethostbyname's possible error codes.

EDIT: You say you have seemingly identical parameters. Can you find a way to prove this (to yourself). Maybe there are invisible characters that got in there? A new line \n, or perhaps it uses a different encoding? Just some ideas.

于 2013-03-12T05:07:34.397 回答
1

Writing my comments as an answer: You should print the URL in a way which lets you see if there are extra chars, even whitespace. Then you should check error codes of all functions you use, like here read the documentation of gethostbyname through. A debug version of your function below, and with that you need the 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);
    }

A guess of a reason: your url from cin has whitespace in it.

A note on terminology: that address string, it is not really url, url must have scheme like http:// at the start. What you have there is a fully qualified domain name of the host, as it should be too, gethostbyname does not understand urls.

于 2013-03-12T07:05:24.673 回答