Android de Communication UDP

J'ai lu de nombreux messages sur ce site sur la façon de recevoir des paquets UDP dans Android. Cependant, rien de tout cela fonctionne pour moi!

Quelques notions de base:

Je suis en train de tester sur mon HTC Incredible (Android 2.2) en cours d'exécution sur la 3G (pas de wifi ou autre chose). Pas d'émulateurs sont en cause ici.

Mon code est simple:

  1. Mon serveur (qui fonctionne sur mon PC) est à l'écoute pour le trafic UDP sur le port 8752.
  2. Mon application Android ouvre une DatagramSocket sur un port aléatoire et envoie un paquet à mon serveur avec ce port.
  3. J'ai ensuite enregistrer cette information (InetAddress forme le paquet reçu et le port trouvés dans le paquet).
  4. J'essaie d'envoyer un paquet UDP à partir de mon serveur (encore une fois, sur mon PC) de mon application Android (en cours d'exécution sur mon téléphone) et il ne fonctionne PAS.
//Server code to initialize the UDP socket (snippet)
public void init() {
    datagram_server_socket = new DatagramSocket(port,local_addr);
    datagram_server_socket.setSoTimeout(1000);
}

//Extrait de code sur l'APPLICATION ANDROID qui envoie un paquet au serveur

public void connect() {
    Random r = new Random(System.currentTimeMillis());
    int udp_port = 0;
    while(true){
        try {
            udp_port = r.nextInt(1000)+8000;
            udp_port = 8000;
            comm_skt = new DatagramSocket(udp_port);
            Log.i("ServerWrapper", "UDP Listening on port: " + udp_port);
            break;
        } catch(SocketException e) {
            Log.e("ServerWrapper", "Could not bind to port " + udp_port);
        }
    }
    byte[] sdata = new byte[4+tid.length];
    i = 0;
    sdata[i++] = (byte)(0XFF&(udp_port>>24));
    sdata[i++] = (byte)(0XFF&(udp_port>>16));
    sdata[i++] = (byte)(0XFF&(udp_port>>8));
    sdata[i++] = (byte)(0XFF&(udp_port));
    for(byte b: tid){
        sdata[i++] = b;
    }
    DatagramPacket pkt = new DatagramPacket(sdata, sdata.length, 
                                InetAddress.getByName(hostname), port);
    comm_skt.send(pkt);
}
//Server's UDP socket listening code
public void serverUDPListener() {
    try {
        datagram_server_socket.receive(rpkt);
        int port = 0;
        byte[] rdata = rpkt.getData();
        port += rdata[0]<<24;
        port += rdata[1]<<16;
        port += rdata[2]<<8;
        port += (0XFF)&rdata[3];
        byte[] tid = new byte[rdata.length];
        for(int i = 4; i < rdata.length && rdata[i] > 0; i++) {
            tid[i-4] = rdata[i];
        }
        String thread_id = new String(tid).trim();
        for(int i = 0; i < threads.size(); i++) {
        ClientThread t = threads.get(i);
        if(t.getThreadId().compareTo(thread_id) == 0) {
            t.setCommSocket(rpkt, port);
        } else {
            System.err.println("THREAD ID " + thread_id + " COULD NOT BE FOUND");
        }
        }
    } catch (IOException e) {
        if(!(e instanceof SocketException) && !(e instanceof SocketTimeoutException))
        log.warning("Error while listening for an UDP Packet.");
    }
}
//Corresponds to the setCommSocket call above to save the IP and Port of the incoming UDP packet on the server-end
public void setCommSocket(DatagramPacket pkt, int port) {
    comm_ip = pkt.getAddress();
    comm_port = pkt.getPort(); //Try the port from the packet?
}
//Sends an UDP packet from the SERVER to the ANDROID APP
public void sendIdle() {
    if(comm_ip != null) {
        System.err.println("Sent IDLE Packet (" + comm_ip.getHostAddress() + ":" + comm_port + ")");
        DatagramPacket spkt = new DatagramPacket(new byte[]{1, ProtocolWrapper.IDLE}, 2, comm_ip, comm_port);
        DatagramSocket skt;
        try {
            skt = new DatagramSocket();
            skt.send(spkt);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Droit maintenant, je l'ai codé en dur le port de mon application utilise à 8000. Cependant, ce qui est bizarre, c'est que CHAQUE fois que je test mon programme (et afficher l'adresse IP et le Port qui est enregistré sur mon serveur), le port le paquet est toujours 33081. J'ai un fil, toujours à l'écoute pour le trafic UDP dans mon Application Android, mais le code ne s'exécute jamais passé le "recevoir(paquet)" partie:

public void AndroidUDPListener() {
    while(true) {
        synchronized(stop) {
        if(stop) return;
        }
        byte[] recieve_data = new byte[64];
        DatagramPacket rpkt = new DatagramPacket(recieve_data, recieve_data.length);
        try {
        if(comm_skt == null) 
                continue;
        comm_skt.receive(rpkt);
        byte[] data = rpkt.getData();
        switch(data[1]) {
            case IDLE:
            if(ocl != null) ocl.onCompletion(null);
            break;
            case KEEP_ALIVE:
            break;
        }
        } catch (Exception e) {
        if(!(e instanceof SocketException) && !(e instanceof SocketTimeoutException))
                Log.w("ServerWrapper", "Error while listening for an UDP Packet.");
        }
    }
}

N'quelqu'un voit un problème dans mon code? Ou est-il une autorisation/paramètres que je dois mettre sur ma demande en premier? J'ai de la communication internet activé.

Exemple de Sortie (en utilisant le port de la trame getPort()):

Application Android - Maintenant à l'écoute pour le trafic UDP sur le port 8000

Android App - l'Envoi de paquets de serveur

Serveur de réception des paquets de XXXXXX:33081

Serveur d'Envoi d'INACTIVITÉ paquet de XXXXXX:33081

Exemple de Sortie (en utilisant le port de données par paquets):

Application Android - Maintenant à l'écoute pour le trafic UDP sur le port 8000

Android App - l'Envoi de paquets de serveur

Serveur de réception des paquets de XXXXXX:8000

Serveur d'Envoi d'INACTIVITÉ paquet de XXXXXX:8000

L'Application Android ne reçoit jamais de tout le trafic UDP à partir de l'aide de l'un des ports.

Pouvez-vous obtenir que cela fonctionne sur les deux ordinateurs de bureau/ordinateurs portables (sans votre téléphone android)? Si vous pouvez éliminer le téléphone comme un problème, alors on peut supposer que c'est un problème avec votre code.
J'ai pu mettre mon téléphone sur mon réseau WiFi et obtenir les paquets UDP de travail de cette façon (en utilisant l'IP de ma machine que le nom d'hôte, en utilisant le DNS externe de nom n'a PAS fonctionné). J'ai aussi eu mon ami le test d'un programme que j'ai écrit pour simuler le Android App réseau appelle à son domicile (en utilisant le DNS externe de nom) et il a bien fonctionné (après avoir fait quelques redirection de port et en forçant un non-port UDP aléatoire). J'espère que cela clarifie la question de mon code.

OriginalL'auteur someone1 | 2011-05-05