Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 将套接字绑定到计算机';听众的地址_C_Sockets_Unix Socket_Getaddrinfo - Fatal编程技术网

C 将套接字绑定到计算机';听众的地址

C 将套接字绑定到计算机';听众的地址,c,sockets,unix-socket,getaddrinfo,C,Sockets,Unix Socket,Getaddrinfo,我创建了一些代码,用于将一个新套接字绑定到计算机的地址,以便侦听特定端口上的传入连接。我正在使用getaddrinfo。这是最好的方式吗?将端口整数转换为字符串似乎毫无意义。有没有一种不需要sprintf就可以做到这一点的方法 bool CBSocketBind(void * socketID,u_int16_t port){ struct addrinfo hints,*res,*ptr; int socketIDInt; // Set hints for the co

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

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

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

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

好,谢谢。如果我设计getaddrinfo,我会为http等常见协议提供常量,而不是使用字符串。但是如果这是惯用的方法,那么我就只能这样了。当然不是什么大问题,我只是不喜欢这样做。如果有人提出改进建议,我还是会看一看。@MatthewMitchell“http”不是常量的原因是管理员可以添加新服务以及更改现有服务的默认端口。请参阅计算机上的
/etc/services
。是的,但端口名可以是有符号整数,其中服务常量为负数,映射到系统使用的端口号。但这并不重要。就是这样,你在反对70年代创造的东西。他们当时知道http吗?:)@MatthewMitchell制作类似于(1)门户、(2)未来证明和(3)通用性的东西的唯一方法是不使用预定义的常量。如果MatthewMitchellProtocol(MMP)在未来起飞呢?任何头文件中没有MMP integer常量的人都将受到惩罚。同时,每个有远见的人只要简单地使用字符串表示就可以了。好的,谢谢,不过如果有更好的方法绑定套接字以侦听传入的连接(据任何人说),我愿意阅读建议。