hel*_*lp 2 c bittorrent udp tcp 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;
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是它http://tracker.thepiratebay.org/是一个URL,但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);
Run Code Online (Sandbox Code Playgroud)
这不仅可以获得所需主机的地址,还可以填写端口号.您可以使用"http"端口,或者您可以使用"80"端口,它们是相同的东西(只要/etc/services有正确的条目).
这条线错了.
memcpy( (char *) &servAddr.sin_addr.s_addr, (char *) hp->h_addr, hp->h_length );
Run Code Online (Sandbox Code Playgroud)
你不知道gethostbyname()返回了一个IPv4地址,尝试将其复制到一个地址是愚蠢的struct sockaddr_in.如果gethostbyname()返回一个IPv6地址,你刚刚破坏了你的堆栈,你的程序将崩溃 - 或者更糟糕的是,它可能不会崩溃.
检查它是否返回IPv4地址,或者只是复制hp->h_addr到struct sockaddr从中返回的泛型malloc(hp->h_length).这有点难看,但它就是它的方式.
最后,将参数强制转换为错误memcpy().这不是错误,但这是错误的.不这样做,可能会导致被抑制,否则合法的编译器错误,例如,如果你不小心施放int到char *.