我目前正在尝试在Android上实现UDP打洞,以用于我的UDP服务器。工作原理如下:
1.客户端(位于NAT后面;可能是3G等)向服务器(具有公共IP;端口也已知为45555)发送DatagramPacket。客户端会重复发送带有给定延迟的Datagram。
2.一旦服务器接收到Datagram,它会每500毫秒发送Datagrams(“信号”)。
3.如果打洞成功,客户端应该接收到这些信号。
以下是我当前的客户端实现(Android):
当客户端和服务器在同一私有网络中时,一切都正常。为了模拟公共服务器,我在我的计算机上运行服务器端代码,并在我的路由器上设置了一个端口(具有公共IP)。客户端将其数据包发送到路由器的公共IP地址。但是,在这两种情况下(我的智能手机通过我的无线局域网网络/ 3G或E连接到互联网),都没有接收到信号(服务器接收不到客户端的数据包)。
那么为什么打洞过程不起作用呢?
问候
1.客户端(位于NAT后面;可能是3G等)向服务器(具有公共IP;端口也已知为45555)发送DatagramPacket。客户端会重复发送带有给定延迟的Datagram。
2.一旦服务器接收到Datagram,它会每500毫秒发送Datagrams(“信号”)。
3.如果打洞成功,客户端应该接收到这些信号。
以下是我当前的客户端实现(Android):
//in onCreate()
DatagramSocket socket = new DatagramSocket(46222);
socket.setSoTimeout(2000);
final Thread t = new Thread(new Runnable(){
@Override
public void run() {
int delay = Integer.parseInt(e2.getText().toString());//e1 and e2 are EditTexts
String ip = e1.getText().toString();
try {
DatagramPacket packet = new DatagramPacket(new byte[1],1, InetAddress.getByName(ip), 45555);
while(!cleanUp){//cleanUp is set to true in onPause()
lock.lock(); //Lock lock = new ReentrantLock();
socket.send(packet);
lock.unlock();
Thread.sleep(delay);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
if(socket!=null)
socket.close();
}
}
});
final Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
try {
Thread.sleep(1000);
DatagramPacket packet = new DatagramPacket(new byte[1],1);
while(!cleanUp){
lock.lock();
try{
socket.receive(packet);
}catch(SocketTimeoutException e){
lock.unlock();
Thread.sleep(15);
continue;
}
lock.unlock();
final String s = tv.getText().toString()+"signal\n";
MainActivity.this.runOnUiThread(new Runnable(){
@Override
public void run() {
tv.setText(s);//tv is a TextView
}
});
Thread.sleep(10);
}
} catch (Exception e) {
e.printStackTrace();
}
finally{
if(socket!=null)
socket.close();
}
}
});
//start both threads
这是服务器端的实现(Java):
//int static void main(String[] args):
final Thread t = new Thread(new Runnable(){
@Override
public void run() {
try {
DatagramPacket packet = new DatagramPacket(new byte[1],1, addr, port);
DatagramSocket socket = new DatagramSocket();
System.out.println("send");
while(true){
socket.send(packet);
Thread.sleep(500);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
final Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
try {
DatagramPacket packet = new DatagramPacket(new byte[1],1);
DatagramSocket socket = new DatagramSocket(45555);
socket.receive(packet);
addr = packet.getAddress(); //private static field InetAddress addr
port = packet.getPort();
System.out.println(addr+":"+ packet.getPort()); //field int port
t.start();
while(true){
socket.receive(packet);
System.out.println("idle");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
t2.start();
当客户端和服务器在同一私有网络中时,一切都正常。为了模拟公共服务器,我在我的计算机上运行服务器端代码,并在我的路由器上设置了一个端口(具有公共IP)。客户端将其数据包发送到路由器的公共IP地址。但是,在这两种情况下(我的智能手机通过我的无线局域网网络/ 3G或E连接到互联网),都没有接收到信号(服务器接收不到客户端的数据包)。
那么为什么打洞过程不起作用呢?
问候