sockets - 如何获得空闲的套接字端口? C++

标签 sockets udp port

我正在编写一个 UDP 测试客户端/服务器,我想让它通过防火墙。据说我需要做的就是让双方发送到正确的 IP 和服务器。获取 IP 不是问题,但我如何让客户端随机选择一个空闲端口并将其报告给用户?我最终希望它连接到匹配服务器,但现在我需要一个简单的工作原型(prototype),并且我想计算端口号,以便我的 friend /测试人员可以通过 IM 向我发送 #,以便我们可以测试。

如何获取端口号? 抱歉这么长的描述。我注意到当我不给出描述时人们告诉我不要做我所要求的事情:(

最佳答案

用高科技术语来说,这实际上是一个非常棘手的问题,甚至是一对棘手的问题。根据防火墙的配置,它通常会允许来自 IP 端点上的另一个端点的响应作为请求的来源。所以...如果您的 friend 使用诸如 recvfrom() 系统调用之类的方式接收 UDP 数据报,则地址参数将接收要响应的 IP 端点信息。因此另一端应该能够使用相同的寻址信息通过 sendto() 进行响应。像这样的东西:

/* initiator */
struct sockaddr_in hisaddr;
memset(&hisaddr, 0, sizeof(hisaddr));
hisaddr.sin_addr.s_addr = htonl(target_ip);
hisaddr.sin_port = htons(target_port);
sendto(sd, msg_ptr, msg_sz, 0, (struct sockaddr*)&hisaddr, sizeof(hisaddr));

/* receiver */
struct sockaddr_in peeraddr;
socklen_t peer_sz = sizeof(peeraddr);
recvfrom(sd, buf_ptr, buf_sz, 0, (struct sockaddr*)&peeraddr, &peer_sz);
/* build response */
sendto(sd, msg_ptr, msg_sz, 0, (struct sockaddr*)&peeraddr, peer_sz);

另一端的 peeraddr 将是您的外部地址,或更准确地说,是您的防火墙的 IP 地址及其选择使用的端口号。您在代码中指定的端口号可能与您的 friend 必须向其发送数据的端口完全不同。最终,您选择使用哪个端口可能并不重要,因为防火墙可能在完全不同的端口上发送和接收 - 这就是 Network Address Translation就是这样。我建议阅读RFC3235了解有关如何克服这一障碍的一些技巧。

恕我直言,最好的方法是:

  1. 让操作系统通过调用 bind() 选择端口端口号为零或完全跳过绑定(bind)
  2. 让客户端从套接字层接收地址信息(例如 recvfrom() 的第五个和第六个参数)
  3. 客户端将响应发送到上一步中检索到的端点
  4. 调整防火墙配置,直到前面的步骤起作用

当然,所有的魔力都在最后一步。如果您可以禁用 NAT 或确保防火墙永远不会切换端口,那么确定端口号并绑定(bind)到它也将起作用。您可能需要查看 %WINDIR%\system32\drivers\etc\services (或 /etc/services 取决于您的操作系统倾向)以了解保留或通常使用哪些端口号。

关于sockets - 如何获得空闲的套接字端口? C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/803012/

相关文章:

python - 格式化并从 JS 发送无缝音频到本地 PyAudio

web-services - Kubernetes: "persistent"端口转发

docker - 在Docker容器中使用iptables进行端口转发

c - C 语言中 sendto() 和 recvfrom() 形式参数的区别

ios - 是否可以在不使用 ffmpeg 的情况下使用 iOS AVPlayer 播放远程 mp4?

c# - 拒绝访问端口 "COM1"

linux - 如何释放socket?

python - 防止第二个进程监听 Python 中的同一个管道

c# - Silverlight 3 可以打开套接字吗?

c - 将 UDP 数据包发送到死服务器