【问题标题】:Binding socket to computer's address for listening将套接字绑定到计算机的地址以进行侦听
【发布时间】:2012-07-15 13:20:41
【问题描述】:

我创建的代码旨在将新套接字绑定到计算机地址,以侦听特定端口上的传入连接。我正在使用 getaddrinfo。这是最好的方法吗?将端口整数转换为字符串似乎毫无意义。有没有不需要 sprintf 的方法来做到这一点?

bool CBSocketBind(void * socketID,u_int16_t port){
    struct addrinfo hints,*res,*ptr;
    int socketIDInt;
    // Set hints for the computer's addresses.
    memset(&hints, 0, sizeof(hints));
    hints.ai_flags = AI_PASSIVE;
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    // Get host for listening
    char portStr[6];
    sprintf(portStr, "%u",port);
    if (getaddrinfo(NULL, portStr, &hints, &res) != 0)
        return false;
    // Attempt to bind to one of the addresses.
    for(ptr = res; ptr != NULL; ptr = ptr->ai_next) {
        if ((socketIDInt = socket(ptr->ai_family, ptr->ai_socktype,ptr->ai_protocol)) == -1)
            continue;
        if (bind(socketIDInt, ptr->ai_addr, ptr->ai_addrlen) == -1) {
            close(socketIDInt);
            continue;
        }
        break; // Success.
    }
    freeaddrinfo(res);
    if (ptr == NULL) // Failure
        return false;
    socketID = malloc(sizeof(int));
    *(int *)socketID = socketIDInt; // Set socket ID
    // Make socket non-blocking
    fcntl(socketIDInt,F_SETFL,fcntl(socketIDInt,F_GETFL,0) | O_NONBLOCK);
    return true;
}

【问题讨论】:

    标签: c sockets unix-socket getaddrinfo


    【解决方案1】:

    getaddrinfo() 的设计旨在适应任何网络协议,这些协议可能对特定服务使用不同的名称。指定可能不是数字,或者可能使用比 TCP 使用的 16 位整数端口号更大的数字。为了最大的灵活性,可以提供一个服务名称,它可以被翻译成一个协议和任何其他特定于协议的信息,例如。 ftp → IPv4 或 IPv6 TCP 端口 21。如果您知道您将始终使用 IPv4 或 IPv6 和 TCP,那么您可以传递 NULL 作为服务名称,并在返回的套接字地址结构中自己填写端口号( sin_port 字段用于 IPv4 或 sin6_port 字段用于 IPv6)。但是,使用sprintf() 可能更干净;这将处理 IPv4 和 IPv6 使用的不同套接字地址结构,以及以网络字节顺序存储端口号的要求,并且还可能允许您在不更改代码的情况下支持其他未来协议。

    【讨论】:

      【解决方案2】:

      getaddrinfo() 采用字符串而不是整数的原因是 服务 不必只是一个端口。例如,用户可以请求服务“http”。

      【讨论】:

      • 好的,谢谢。如果我正在设计 getaddrinfo,我会为常见协议(例如 http)提供常量,而不是使用字符串。但是,如果这是惯用的做法,那么我就只能这样了。当然不是什么大问题,我只是不喜欢它的完成方式。如果有人有改进建议,我仍然会看看。
      • @MatthewMitchell “http”不是常量的原因是管理员可以添加新服务以及更改现有服务的默认端口。在您的机器上查看/etc/services
      • 是的,尽管端口名称可以是有符号整数,其中服务常量是映射到系统使用的端口号的负数。但这没关系。就是这样。
      • 你在反对 70 年代创造的东西。他们知道http吗? :)
      • @MatthewMitchell 制作这样 (1) 门户、(2) 面向未来和 (3) 通用的东西的唯一方法是使用 pre-定义的常量。如果 MatthewMitchellProtocol (MMP) 在未来起飞会怎样?任何在他的头文件中没有 MMP 整数常量的人都会被搞砸。同时,任何有远见的人都可以简单地使用字符串表示。
      【解决方案3】:

      AI_PASSIVE 状态下通常如何使用getaddrinfo() 看起来相当地道。字符串化的数字是典型的。

      【讨论】:

      • 好的,谢谢,但如果有更好的方法来绑定套接字以侦听传入连接(根据任何人的说法),我愿意阅读建议。
      猜你喜欢
      • 1970-01-01
      • 2011-02-24
      • 1970-01-01
      • 1970-01-01
      • 2021-11-09
      • 1970-01-01
      • 2020-02-20
      • 1970-01-01
      • 2017-04-27
      相关资源
      最近更新 更多