2

我创建了旨在将新套接字绑定到计算机地址的代码,以侦听特定端口上的传入连接。我正在使用 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;
}
4

3 回答 3

3

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

于 2012-07-16T19:43:15.407 回答
2

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

于 2012-07-16T16:46:04.883 回答
1

这看起来非常习惯于在状态getaddrinfo()中通常使用的方式。AI_PASSIVE字符串化的数字是典型的。

于 2012-07-16T16:42:58.400 回答