【问题标题】:Get random port for socket获取套接字的随机端口
【发布时间】:2025-11-22 00:50:02
【问题描述】:

我知道这个问题已经被问过了,但我似乎有点“特别”,因为我的代码不起作用。 指令是“与端口 0 绑定并使用getsockname 获取端口”。我做错了什么...

struct sockaddr_in sa;

sa.sin_port=htons(0);
sa.sin_addr.s_addr=htonl(INADDR_ANY);
sa.sin_family=AF_INET;

int sock;
sock = socket(AF_INET, SOCK_STREAM, 0);

struct sockaddr *serverptr = (struct sockaddr*)&sa;
bind(sock, serverptr,sizeof(sa));
socklen_t s=sizeof(sa);
int g=getsockname(sock,serverptr,&s);

g 总是打印为 0。

编辑:它非常简单,只是 sa.sin_port 愚蠢的问题。

【问题讨论】:

  • g 总是打印为 0。 - 你读过 getsockname 文档吗?它明确指出“成功时返回零。出错时返回-1,并适当设置errno。

标签: c sockets port bind


【解决方案1】:

大多数 Berkley Socket API 函数使用非常简单的约定:返回的结果是操作成功的指示。因此,零表示正常,负数表示错误。为了安全起见,您必须始终检查它,并且您的代码缺少对 socket()bind()getsockname() 调用的验证:

...
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
    // log the error, etc
    return;
}
int res = bind(sock, serverptr, sizeof(sa));
if (res < 0) {
    // log the error, etc
    close(sock);
    return;
}
socklen_t s = sizeof(sa);
res = getsockname(sock, serverptr, &s);
if (res < 0) {
    // log the error, etc
    close(sock);
    return;
}
...

【讨论】:

  • "所以,零表示 OK" - 更准确地说,不是负数表示 OK,因为并非所有套接字函数在成功时都返回 0(例如,recv()),但是失败时它们都返回负数(通常为 -1)。
  • 感谢@RemyLebeau,旧的记忆并不总是正确的:)