Java Android上的UDP打孔;UDP服务器
我目前正在尝试为我的udp服务器在Android上实现udp打孔。事情应该是这样的:Java Android上的UDP打孔;UDP服务器,java,android,network-programming,udp,hole-punching,Java,Android,Network Programming,Udp,Hole Punching,我目前正在尝试为我的udp服务器在Android上实现udp打孔。事情应该是这样的: 客户端(nat后面;可能是3G,…)向服务器发送数据包(服务器有一个公共ip;端口也被称为45555)。客户端以给定的延迟重复发送数据报 一旦服务器收到数据报,它每500毫秒发送一次数据报(“信号”) 如果打孔成功,客户应收到这些信号 以下是我当前的客户端实现(Android): 以下是服务器端实现(Java): 当客户机和服务器在同一个专用网络中时,一切都正常工作。为了模拟公共服务器,我在计算机上运行服务器端
*:路由器会将发送到其端口45555的任何udp数据包转发到我的计算机不同的套接字绑定到不同的专用端口,并使用NAT的不同公共端口。您通过不同的套接字进行接收和发送。使用接收数据的同一套接字发送。否则,发送套接字将使用路由器的不同公共端口向客户端NAT发送数据。您的客户端NAT丢弃此数据包,因为它来自相同的IP但未知的端口。您所说的“在我的路由器上设置端口”是什么意思?你所做的不是打孔。穿孔用于在不同NAT后面的两个客户端之间建立对等连接。路由器将把发送到其端口45555的任何udp数据包转发到my computerThx,这应该是问题所在。但是,在服务器端,我希望同时接收和发送数据报。在JavaSocket中,有没有一种方法可以在同一个套接字(或使用同一端口)上同时发送和接收数据报?套接字是双向的,因此您可以同时发送和接收数据。但是您可能需要处理一个线程突然关闭套接字的情况。
//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
//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();