Java 为什么UDP打孔不适用于公共IP地址?
下面有两个Groovy子程序通过普通UDP套接字相互发送消息。当消息发送到Java 为什么UDP打孔不适用于公共IP地址?,java,groovy,udp,stun,Java,Groovy,Udp,Stun,下面有两个Groovy子程序通过普通UDP套接字相互发送消息。当消息发送到127.0.0.1时,他们确实成功地接收到消息。但是当将消息发送到公共IP地址时(机器在NAT后面)不会收到消息 为什么不打孔?如何解决这个问题 早些时候,我尝试通过Java库查询公共STUN服务器,但它以相同的公共IP地址响应我,因此我在这里使用wtfismyip.com class GroovyTest { static String PUBLIC_IP = new URL('https://wtfismyip.co
127.0.0.1
时,他们确实成功地接收到消息。但是当将消息发送到公共IP地址时(机器在NAT后面)不会收到消息
为什么不打孔?如何解决这个问题
早些时候,我尝试通过Java库查询公共STUN服务器,但它以相同的公共IP地址响应我,因此我在这里使用wtfismyip.com
class GroovyTest {
static String PUBLIC_IP = new URL('https://wtfismyip.com/text').text.trim()
//static String PUBLIC_IP = '127.0.0.1' // works fine
static void main(String[] args) {
runInstance(11111, 22222)
runInstance(22222, 11111)
}
static void runInstance(int thisPort, int anotherPort) {
def socket = new DatagramSocket(thisPort)
Thread.start {
// message listener
byte[] buf = new byte[1024]
while (true) {
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
InetAddress remoteAddr = packet.getAddress();
int remotePort = packet.getPort();
String sentence = new String(packet.getData(), 0, packet.length);
println("server-$thisPort: received [$sentence] from ${remoteAddr.hostAddress}:${remotePort}")
}
}
Thread.start {
// message sender
while (true) {
println("client-$thisPort: sending to ${PUBLIC_IP}:${anotherPort}...")
byte[] buf = ("Hello " + System.currentTimeMillis()).bytes
DatagramPacket packet = new DatagramPacket(buf, buf.length, InetAddress.getByName(PUBLIC_IP), anotherPort)
socket.send(packet)
Thread.sleep(2000)
}
}
}
}
您的问题源于wtfismyip返回的IP地址是网络上路由器的IP地址,而该地址未分配给您的计算机。当您尝试向路由器的公共IP发送数据报时,您可能会从路由器收到无法访问ICMP目的地和ICMP目的地的错误消息。如果您需要此行为,您的路由器可能具有某些端口转发功能,可以将入站UDP通信转发到您的本地IP地址。您的问题源于wtfismyip返回的IP地址是网络上路由器的IP地址,而该地址未分配给您的计算机。当您尝试向路由器的公共IP发送数据报时,您可能会从路由器收到无法访问ICMP目的地和ICMP目的地的错误消息。如果您需要这种行为,您的路由器可能具有一些端口转发功能,可以将入站UDP通信转发到您的本地IP地址。我已经成功地在NAT路由器后面回复UDP数据包,只需从我正在响应的UDP数据包中获取地址和端口详细信息
DatagramSocket socket = new DatagramSocket(port);
DatagramPacket receivePacket = new DatagramPacket(receiveBuffer, receiveBuffer.length);
socket.receive(receivePacket);
DatagramPacket sendPacket = new DatagramPacket(sendBuffer, sendBuffer.length,
receivePacket.getAddress(), receivePacket.getPort());
socket.send(sendPacket);
该代码更健壮,因为它不在乎数据包来自何处,也不在乎沿途发生的任何地址转换。它将始终回复到正确的位置
我还注意到您使用了两个不同的端口号。“此端口”和“其他端口”。据我所知,打孔将只工作,如果你回复相同的端口号。出于安全原因,这是有意义的
我头顶上的海洋机器人,如我的头像所示,使用这种UDP打孔技术。我已经成功地在NAT路由器后面回复UDP数据包,只需从我响应的UDP数据包中获取地址和端口详细信息
DatagramSocket socket = new DatagramSocket(port);
DatagramPacket receivePacket = new DatagramPacket(receiveBuffer, receiveBuffer.length);
socket.receive(receivePacket);
DatagramPacket sendPacket = new DatagramPacket(sendBuffer, sendBuffer.length,
receivePacket.getAddress(), receivePacket.getPort());
socket.send(sendPacket);
该代码更健壮,因为它不在乎数据包来自何处,也不在乎沿途发生的任何地址转换。它将始终回复到正确的位置
我还注意到您使用了两个不同的端口号。“此端口”和“其他端口”。据我所知,打孔将只工作,如果你回复相同的端口号。出于安全原因,这是有意义的
我头上的海洋机器人,如我的头像所示,使用这种UDP打孔技术。
newURL('https://wtfismyip.com/text).text.trim()
-真的吗?@shmosel-Oh-Groovy新URL('https://wtfismyip.com/text“).text.trim()
-真的吗?@shmosel-Oh-Groovy