Attualmente sto cercando di implementare la punzonatura di udp su Android per il mio server udp. Le cose dovrebbero funzionare in questo modo:Punzonatura fori UDP su Android; Server UDP
- Il cliente (dietro un NAT, forse 3G, ..) invia un DatagramPacket al server (il server ha un IP pubblico; porta è noto anche per essere 45555). Il client si ripete per inviare un datagramma con un determinato ritardo
- Una volta che il server ha ricevuto un datagramma, invia i datagrammi ("segnali") ogni 500ms.
- Se perforazione lavorato, il cliente deve ricevere i segnali
Ecco il mio attuale implementazione client (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
Qui è l'implementazione lato server (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();
Tutto funziona quando client e server si trovano nella stessa rete privata. Per imitare il server pubblico eseguo il codice lato server sul mio computer e configuro una porta sul mio router (che ha un ip pubblico) *. I client invieranno i propri pacchetti all'IP pubblico del router. Ma in entrambi i casi (il mio smartphone è connesso ad internet tramite la mia rete wlan/3G o E) non vengono ricevuti segnali (il server riceve i datagrammi del client)
Quindi perché il processo di perforazione non funziona?
riguarda
*: Il router inoltrerà i pacchetti UDP inviati al suo porto 45555 al mio computer
Cosa intendi per "configurare una porta sul mio router"? E quello che stai facendo non è perforare. La perforatura viene utilizzata per stabilire una connessione peer-to-peer tra due client dietro NAT diversi. – Tahlil
Il router inoltrerà tutti i pacchetti udp inviati alla sua porta 45555 al mio computer – user2224350