Domanda

I am tying to connect to a bit torrent tracker, http://tracker.thepiratebay.org. The gethostbyname() keeps returning null, how should I fix this? Also do you see anything else wrong with this code?

    int sock;
    struct sockaddr_in servAddr; 
    int portNum = 80;

    if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0){
          printf("fail create socket");
          return 0;
    }

    char *path = "http://tracker.thepiratebay.org/";
    struct hostent *hp = gethostbyname(path);   
    if(hp==NULL){
        printf("null");
    else{

        memset(&servAddr, 0, sizeof(servAddr));   
        servAddr.sin_family = AF_INET;                 
        memcpy( (char *) &servAddr.sin_addr.s_addr, (char *)  hp->h_addr, hp->h_length );
        servAddr.sin_port   = htons(portNum);    
    }

    //send request to tracker server 
    if (send(sock, requestToSend, strlen(requestToSend), 0) != strlen(requestToSend)){
        printf("fail send");
        return 0;
    }
È stato utile?

Soluzione

The problem here is that http://tracker.thepiratebay.org/ is a URL, but gethostbyname() expects just the host name. The host name is tracker.thepiratebay.org.

It would make it much easier if you just use libcurl, which will handle all of that HTTP stuff for you. It is extremely common to use libcurl in applications that connect to HTTP servers; it is an excellent library. It's certainly easier than socket programming.

Use getaddrinfo()

The modern alternative to gethostbyname() is getaddrinfo(). It's not that gethostbyname() doesn't do what you want, rather, getaddrinfo() is simply better in every conceivable way.

struct addrinfo hint, *ap;
memset(&hint, 0, sizeof(hint));
hint.ai_family = AF_UNSPEC;
hint.ai_socktype = SOCK_STREAM;
int r = getaddrinfo("tracker.thepiratebay.org", "http", &hint, &ap);

This will not only get you the address for the host you want, but it will also fill in the port number. You can use "http" as the port, or you can use "80" for the port, they are the same thing (as long as /etc/services has the right entry).

Other problems

This line is wrong.

memcpy( (char *) &servAddr.sin_addr.s_addr, (char *)  hp->h_addr, hp->h_length );

You don't know that gethostbyname() returned an IPv4 address, and it is foolish to try and copy it into a struct sockaddr_in. If gethostbyname() returned an IPv6 address, you have just smashed your stack and your program will crash -- or worse, it might not crash.

Either check that it returns an IPv4 address, or simply copy hp->h_addr into a generic struct sockaddr that was returned from malloc(hp->h_length). This is a bit ugly but it's the way it goes.

Finally, it is wrong to cast the arguments to memcpy(). It's not an error, but it's wrong. Don't do it, it can cause otherwise legitimate compiler errors to be suppressed, e.g., if you accidentally cast an int to char *.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top