【问题标题】:What's the purpose of using bind() when SOCK_DGRAM is used?使用 SOCK_DGRAM 时使用 bind() 的目的是什么?
【发布时间】:2021-10-23 02:12:01
【问题描述】:

这是一段来自tftp的sn-p代码

void initsock(int af) {
    struct sockaddr_storage s_in;

    if (f >= 0)
        close(f);

    f = socket(af, SOCK_DGRAM, 0);
    if (f < 0) {
        perror("tftp: socket");
        exit(3);
    }
    printf("protocol family: %d\n", af);

    memset(&s_in, 0, sizeof(s_in));
    s_in.ss_family = af;
    if (bind(f, (struct sockaddr *)&s_in, sizeof (s_in)) < 0) {
        perror("tftp: bind");
        exit(1);
    }
    char ip_str[INET6_ADDRSTRLEN] = {0};

    inet_ntop(s_in.ss_family, get_in_addr((struct sockaddr *)&s_in), ip_str, sizeof ip_str);
    printf("ip address: %s\t port: %d\n", ip_str, get_in_port((struct sockaddr *)&s_in));
}

我的问题是为什么在这里调用 bind() ?目的是什么?第二个参数似乎是空的,除了 ss_family 字段,没有 IP 地址或端口号。

附言源代码来自https://packages.ubuntu.com/bionic/tftp

【问题讨论】:

  • 这个 sn-p 来自什么 TFTP 实现?你能发布一个存储库的链接吗?
  • 看起来它用于使用“ANY”地址和临时端口绑定到 IPv4 或 IPv6。所以基本上是选择要使用的 IP 版本。

标签: c sockets tftp


【解决方案1】:

bind() 在此示例中使用 INADDR_ANY 作为地址,这意味着 它绑定到man 2 bind 的所有可用接口和端口 0 指的是 临时端口 这意味着它允许操作 系统选择要使用的空闲端口。可以在这个函数最后加上如下sn -p,使用getsockname()得到 操作系统选择的端口号:

    struct sockaddr_in sa;
    socklen_t addrlen = sizeof(sa);

    if (getsockname(f, (struct sockaddr *) &sa, &addrlen) == -1) {
      perror("getsockname()");
    }

    printf("Local IP address is: %s\n", inet_ntoa(sa.sin_addr));
    printf("Local port is: %d\n", (int) ntohs(sa.sin_port));

【讨论】:

  • 谢谢。临时端口出现在 ERRORS 部分,当我阅读时被忽略了。现在我知道了 bind() 这里的功能,但目的仍然不清楚。我的意思是调用 sendto() 时可以选择接口和端口号。那何必在这里打扰。客户端不使用端口号,因为如果这是获取端口号的常用方法,我搜索并没有找到 getsockname 结果。
  • 我下载了archive.ubuntu.com/ubuntu/pool/universe/n/netkit-tftp/…,但没有名为initsock()的函数。所以让我再问一次 - 你问题中的这个 sn-p 来自哪里?
  • @ArkadiuszDrabczyk:显然来自应用到源代码的 ubuntu 补丁,archive.ubuntu.com/ubuntu/pool/universe/n/netkit-tftp/…
  • @ArkadiuszDrabczyk 正如 Hasturkun 所说,它来自 ubuntu 添加到 orig 的补丁。实际上,我什至没有注意到这一点,因为我是使用 apt-get source 下载的。原谅我的粗心。应用补丁后,它位于 tftp/main.c
  • @ArkadiuszDrabczyk "你可以...使用getsockname() 来获取操作系统选择的端口号" - 这可能是对get_in_addr() 和@ 的调用987654330@实际上是在内部做的,在printf()之前bind()之后。
猜你喜欢
  • 2011-08-14
  • 2013-02-04
  • 1970-01-01
  • 1970-01-01
  • 2016-10-29
  • 2016-02-23
  • 1970-01-01
  • 2021-01-31
  • 2011-10-17
相关资源
最近更新 更多