我正在编写UDP测试客户端/服务器,我希望通过防火墙.据说我需要做的就是让双方都发送到正确的IP和服务器.获取IP不是问题,但我如何让客户端选择随机空闲端口并将其报告给用户?我最终希望它连接到一个媒人服务器,但现在我需要一个简单的工作原型,我想cout端口号,所以我的朋友/测试人员可以通过IM发送#我们可以测试.
我如何获得端口号?抱歉,长期的desc.我注意到人们告诉我不要做什么,当我不给desc时我问的问题:(
要使用高技术术语,这实际上是一个非常棘手的问题,甚至是一对棘手的问题.根据防火墙的配置,它通常会在请求来自时允许来自IP端点上另一个端点的响应.所以...如果你的朋友使用类似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地址,它选择使用的端口号.您在代码中指定的端口号可能与您的朋友必须向其发送数据的端口完全不同.最终,由于防火墙可能在完全不同的端口上发送和接收,因此您选择使用哪个端口可能并不重要 - 这就是网络地址转换的全部内容.我建议阅读RFC3235以获取有关如何克服这一障碍的一些提示.
恕我直言的最佳方法是:
让操作系统通过使用bind()
零端口号调用或完全跳过绑定来选择端口
让客户端从套接字层接收地址信息(例如,第五和第六个参数recvfrom()
)
客户端将响应发送到上一步中检索到的端点
调整防火墙配置,直到前面的步骤工作
当然,所有的魔力都在最后一步.如果您可以禁用NAT或确保防火墙永远不会切换端口,那么确定端口号并且bind
-ing也可以正常工作.您可能需要查看%WINDIR%\system32\drivers\etc\services
(或/etc/services
根据您的操作系统倾向)来了解保留或通常使用的端口号.