我正在通过编写一个向指定服务器发送DNS查询的小应用程序来学习C.以下是网络代码的示例:
int send_query()
{
int sockfd;
struct sockaddr_in server;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
perror("cannot create socket\n");
}
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(53);
inet_pton(AF_INET, "8.8.8.8", &(server.sin_addr));
sendto(sockfd, const void *buffer, size_t length, 0, (struct sockaddr *) &server, sizeof(server));
}
这样可以正常运行查询,并收到回复。但是,通过使用Wireshark嗅探流量,我可以看到消息:Destination unreachable (Port unreachable)
。
我发现我可以在bind()
之前调用sendto()
来避免这种情况:
int send_query()
{
int sockfd;
struct sockaddr_in server;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
perror("cannot create socket\n");
}
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(53);
inet_pton(AF_INET, "8.8.8.8", &(server.sin_addr));
if(bind(sockfd, (struct sockaddr *) &server, sizeof(server)) < 0) {
perror("bind failed\n");
}
sendto(sockfd, const void *buffer, size_t length, 0, (struct sockaddr *) &server, sizeof(server));
}
现在Destination unreachable (Port unreachable)
消息已消失,但应用程序必须以root权限运行,因为它将绑定到端口53.
是否可以修改代码,以便使用随机的非特权源端口?
问题已解决
由于一个愚蠢的错误而出现了问题。我只是评论了recvfrom()
。当我在测试应用程序时嗅探流量时,我可以看到计算机上的响应和错误,并且在应用程序正在接收时错误地混淆了这一点。因为我不知道我到底在做什么,所以我开始讨论bind()
等等。这种雪崩的失败开始了。
为了简洁起见,我没有发布所有代码,但如果这样做了,问题可能会立即得到解决。