我之前使用 UDP 打孔制作了一个简单的点对点聊天程序,现在我正在尝试做类似的事情,但在使用 libGDX 制作的游戏中。游戏本身运行良好,连接在 LAN 上工作,但我很难尝试使用外部连接。我了解 UDP 打孔的工作原理如下:
如果 A 和 B 都知道对方的 IP 地址和端口,则:
- A 向 B 发送一个 UDP 数据包,该数据包在 A 的 NAT 上打了一个洞,但被 B 的防火墙丢弃
- A 等待回复
- B 向 A 发送一个 UDP 数据包,该数据包在其自己的 NAT 上打了一个洞并通过 A 的防火墙
- B 等待回复
- A 接收 B 的初始消息并发送第二个消息给 B
- B收到A的消息
我的网络代码属于一类:
private boolean connected;
private DatagramSocket socket;
private DatagramPacket packet;
private InetAddress peerIP;
public NetworkManager(InetAddress peerIP){
this.peerIP = peerIP;
log("Created with peer ip: " + peerIP.getHostAddress());
connected = false;
}
@Override
public void run(){
try{
log("Setting up socket");
socket = new DatagramSocket(Constants.CLIENT_PORT);
log("Socket successfully setup");
//Punch hole
log("Punching UDP Hole");
sendBytes("one");
//Receive
log("Waiting for peer reply");
receiveBytes(3);
//Send second message
if(Arrays.equals(packet.getData(), "one".getBytes()) ){
sendBytes("two");
}
}catch(Exception e){
log("Error connecting to peer");
return;
}
log("Successfully connected");
connected = true;
}
private synchronized void receiveBytes(int length) throws Exception {
packet = new DatagramPacket(new byte[length], length);
log("Receiving " + length + " bytes...");
socket.receive(packet);
log("Received bytes " + packet.getData()+ " from " + packet.getAddress());
}
private synchronized void sendBytes(String s) throws Exception {
byte[] sendBytes = s.getBytes();
packet = new DatagramPacket(sendBytes, sendBytes.length, peerIP, Constants.CLIENT_PORT);
log("Sending " + sendBytes.length + " bytes...");
socket.send(packet);
log("Bytes sent");
}