如何连接到c中的一点洪流跟踪器

时间:2012-12-04 03:58:48

标签: c tcp udp bittorrent tracker

我想要连接到一点洪流跟踪器,http://tracker.thepiratebay.org。 gethostbyname()一直返回null,我该如何解决这个问题?你还看到这个代码有什么问题吗?

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

1 个答案:

答案 0 :(得分:7)

此处的问题是http://tracker.thepiratebay.org/是一个网址,但gethostbyname()只需要主机名。主机名为tracker.thepiratebay.org

如果您只使用libcurl,它会更容易,它将为您处理所有HTTP内容。在连接到HTTP服务器的应用程序中使用libcurl是非常常见的;这是一个很棒的图书馆。它肯定比套接字编程更容易。

使用getaddrinfo()

gethostbyname()的现代替代品是getaddrinfo()。并不是gethostbyname()没有做你想做的事情,而是getaddrinfo()在各种可能的方式中都会更好。

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

这不仅可以获取所需主机的地址,还可以填写端口号。您可以使用"http"作为端口,或者可以使用"80"作为端口,它们是相同的(只要/etc/services有正确的条目)。

其他问题

这条线错了。

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

您不知道gethostbyname()返回了IPv4地址,尝试将其复制到struct sockaddr_in是愚蠢的。如果gethostbyname()返回了IPv6地址,那么您刚刚破坏了堆栈,程序将崩溃 - 或者更糟糕的是,它可能不会崩溃。

检查它是否返回IPv4地址,或者只是将hp->h_addr复制到从struct sockaddr返回的通用malloc(hp->h_length)中。这有点难看,但它就是它的方式。

最后,将参数强制转换为memcpy()是错误的。这不是错误,但这是错误的。不要这样做,它可能会导致其他合法的编译器错误被抑制,例如,如果您不小心将int强制转换为char *