如何获取第一个可用的TCP端口进行监听?

9

我想将我的服务附加到某个TCP端口以进行测试。然后,我会对该端口进行调用,确保服务正常运行,并将其关闭。我需要找到一种方法来生成这样的端口号,因为我无法使用固定的端口号 - 测试可能会并行运行。这是否可能?


POSIX:https://dev59.com/questions/OHNA5IYBdhLWcg3wjOve - Ciro Santilli OurBigBook.com
2个回答

6
这是我的做法:
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main() {
    struct sockaddr_in addr;
    socklen_t len = sizeof(addr);
    addr.sin_port = 0;
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        perror("socket()");
        return -1;
    }
    if (bind(sock, (struct sockaddr*) &addr, sizeof(addr)) != 0) {
        perror("bind()");
        return -1;
    }
    if (getsockname(sock, (struct sockaddr*) &addr, &len) != 0) {
        perror("getsockname()");
        return -1;
    }
    printf("%d\n", addr.sin_port);
    return 0;
}

然后,编译并运行它:
cc -o reserve reserve.c && ./reserve

它会输出可用于绑定的端口号。我在Github上发布了该工具的完整版本:https://github.com/yegor256/random-tcp-port

2
不将 struct sockaddr_in addr 初始化为 0 可能会导致未定义的行为,可能会导致应用程序崩溃。 - alk
1
同时,我们不能依赖于AF_UNSPEC被定义为#define0 - alk
你还没有解释为什么这个方法有效。如果确实有效的话,我不明白它是如何在没有初始化套接字地址结构的情况下工作的。 - user207421
@alk 你是对的,我更新了答案,并明确初始化了 addr.sin_port 为零。 - yegor256
1
你需要对除了 addr.sin_port 以外的部分进行初始化。你需要将 .sin_family 初始化为 AF_INET.sin_addr.s_addr 初始化为 INADDR_ANY - Robᵩ

2

在绑定时指定端口号为0,然后使用getsockname()来查找所分配的端口号,这样你就可以通过其他方式告诉客户端你正在侦听的端口号了。这种方法很少有用。


1
在集成测试期间,当您想要在任何可用端口上启动测试服务器,然后将其传递给相应的测试客户端时,IMO非常有用。此外,当您从“父”程序启动一组相互依赖的子微服务时也很有用。 - morgwai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接