【发布时间】:2014-03-24 18:37:40
【问题描述】:
众所周知,为了将套接字 fd 绑定到随机空闲端口,您将 0 作为 sockaddr_in.sin_port 传递给 bind。但是,这似乎总是从临时端口范围内分配一个端口,如下面的程序 [*] 所示。
我的问题是,有没有一种 [干净的] 方法可以从 非临时 端口范围获取随机端口?
[*]
#include <fstream>
#include <iostream>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
using namespace std;
int main(int argc, char* argv[]) {
fstream ports("/proc/sys/net/ipv4/ip_local_port_range", fstream::in);
int eMin, eMax; ports >> eMin >> eMax;
cout << "ephemeral range: [" << eMin << ", " << eMax << "]" << endl;
for (int i = 0; i < 100; ++i) {
int fd = socket(PF_INET, SOCK_STREAM, 0);
sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
socklen_t addrlen = sizeof(addr);
bind(fd, (sockaddr*)(&addr), addrlen);
getsockname(fd, (sockaddr*)(&addr), &addrlen);
uint16_t port = ntohs(addr.sin_port);
bool within = (port >= eMin) && (port <= eMax);
cout << "port " << port << " " << (within ? "in" : "out") << endl;
close(fd);
}
return 0;
}
附:现在我正在使用的解决方法是从非临时端口范围显式传递一个随机端口号为sockaddr_in.sin_port,尝试绑定到它,如果绑定操作失败,则重复冲洗。但这感觉像是在模仿系统应该提供的东西。
【问题讨论】:
-
我不知道是否有通用方法,但是在例如 linux 上,您可以从 /proc/net 伪文件中知道正在使用哪些端口,因此大概选择一个未使用的端口少一点盲目的试错。
-
出于什么目的?你为什么关心价值是什么?如果这样做,为什么不能使用固定值?
-
我没有看到任何迹象表明这是可能的,而且这是有道理的,因为他们对 ephemeral 的定义本质上是“没人会去的数字”关心,所以可以不假思索地分发。”
-
无法重现...您使用哪个操作系统?