c - UDP套接字的源端口和目标端口?

标签 c linux sockets networking udp

我正在通过编写一个向指定服务器发送 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)

我发现我可以通过在 sendto() 之前调用 bind() 来避免这种情况:

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 权限运行,因为它将绑定(bind)到端口 53。

是否可以修改代码以便改用随机的非特权源端口?

问题已解决

问题的发生是因为一个愚蠢的错误。我只是简单地注释掉了 recvfrom()。当我在测试应用程序时嗅探流量时,我可以看到响应和错误到达我的计算机,并在应用程序接收时错误地将其混淆。因为我不知道自己到底在做什么,所以我开始乱搞 bind() 等,然后就开始了这种雪崩式的失败。

为简洁起见,我没有发布所有代码,但如果这样做的话,问题可能会立即得到解决。

最佳答案

您可以绑定(bind)到端口 0,让操作系统随机选择一个可用的端口(就像 INADDR_ANY 为 0)。参见 https://stackoverflow.com/a/1077305/3543692

此外,绑定(bind)到端口 53 毫无意义。 53端口是DNS服务器的端口,不是DNS客户端的端口。想一想如果你电脑上的所有DNS客户端都使用53作为DNS客户端端口,那么只能同时对一台服务器进行一个DNS请求。通常,所有客户端(包括 TCP/UDP)都使用操作系统分配的随机未使用端口。

关于c - UDP套接字的源端口和目标端口?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29711247/

相关文章:

linux - Linux 中的页面错误是否一定会导致上下文切换?

linux - 如何知道我拥有的 Linux 发行版?

python - 在 Python asyncio 中检测套接字 EOF

c - 反向功能未按预期工作

创建具有 AX.25 封装的 TUN 网络设备

在不使用堆栈的情况下检查带有 3 个差异括号的字符串是否平衡

c++ - 我应该从 main() 返回 EXIT_SUCCESS 还是 0?

linux - mplayer 无法读取 udp 视频流

apache-flex - Action : connect to socket server

java - Android:如何在所有 Activity 中与服务器建立公共(public)套接字连接