我想要连接到一点洪流跟踪器,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;
}
答案 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 *
。