问题
我正在开发一个通信系统,其中:
A、B是NAT下的计算机,A是服务器,B是客户端。 S是STUN服务器。
S运行在一个可以通过互联网访问的机器上。
流程如下:
A hits S with an opcode saying he's the server
S registers A as server
B hits S with an opcode saying he's the client
S sends to A B's external infos (IP, PORT)
S sends to B A's external infos (IP, PORT)
A starts sending B an opcode saying he's the server every 500ms
and meanwhile listens for packets saying he's got a client
B starts sending A an opcode saying he's the client every 500ms
and meanwhile listen for packets saying he's got the server
问题
问题出现在这里,STUN服务器完成了它的工作,因为双方都收到了有关对方的正确信息。
但是我从未收到过另一端的消息,因此双方都在等待握手操作码或任何其他内容而没有接收到。
NAT的行为
我已经检查了这个NAT的行为,似乎是这样的:
A位于192.168.X.X的4444端口上连接到外部暴露的N.N.N.N:4444端口,所以只要端口空闲,端口号就保持不变,如果不可用则会获得一个新的(随机的?)端口号。
测试
我运行的测试看到A和B两端都托管在同一台机器上,并绑定到机器的内部IP,尝试绑定到127.0.0.1、0.0.0.0,但什么也没改变。
如果在等待握手时使用nc
向localhost
发送echo
,则可以接收并显示该消息(作为未识别的消息),没有任何问题。然而通过NAT路由的连接不起作用,每个数据包都被丢弃。
还尝试过将A托管在计算机上,将B托管在移动数据下的Android手机上,使用特别编写的应用程序。仍然等待某些东西,就像nodejs测试一样。
更新:
我尝试做的另一件事是用nc
打开一个洞。
我在同一个NAT下的两台不同机器上运行了以下命令:
echo "GREET UNKOWN PEER" | nc -u <NAT IP> 4567 -p 4568
echo "GREET UNKOWN PEER" | nc -u <NAT IP> 4568 -p 4567
每台机器都运行了多次。据我所知,这应该会在第一个数据包被丢弃并且随后转发之后在NAT中打洞。但是没有任何反应,没有一端收到了消息。
我还尝试了:
从本地机器
echo "GREET UNKOWN PEER" | nc -u <PUBLIC IP> 4567 -p 4568
从公共机器
echo "GREET UNKOWN PEER" | nc -u <NAT IP> 4568 -p 4567
这个可以工作,位于NAT下的本地机器联系公共机器,并在第一个丢弃的数据包之后能够在分配的端口上接收和发送。我想知道为什么这不能在同一NAT下的两台机器上工作(???)
代码
我没有展示任何代码,因为我认为其中存在某种逻辑缺陷,然而这是该GitHub项目的链接。index.js
包含STUN服务器,tests文件夹包含测试用例: test.js
启动stun服务器,PeerClientTest.js
和PeerServerTest.js
是客户端和服务器的模拟。在公共计算机上运行
node tests/test.js
以启动服务器(更改config.js
和tests/config.js
中的IP)然后运行
node tests/PeerServerTest.js
以启动服务器("A"),再运行node tests/PeerClientTest.js
以启动客户端("B")。两者都通过STUN识别对方,然后监听另一端的握手操作码同时发送自己的握手操作码。这从未发生过,因此它们会永远发送/监听。Node不是必需的,所以如果有其他语言的更好解决方案,请告诉我,将不胜感激。