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:
- Mon serveur (qui fonctionne sur mon PC) est à l'écoute pour le trafic UDP sur le port 8752.
- Mon application Android ouvre une DatagramSocket sur un port aléatoire et envoie un paquet à mon serveur avec ce port.
- J'ai ensuite enregistrer cette information (InetAddress forme le paquet reçu et le port trouvés dans le paquet).
- 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.
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
Vous devez vous connecter pour publier un commentaire.
Désolé de ne pas mettre à jour plus tôt. Le problème a été fixé comme suit:
J'avais besoin de stocker les DatagramSocket à chaque thread. La socket d'écoute devrait également être le support utilisé pour la communication continue entre le serveur et le client. Voici les bouts de code mis à jour.
Nouveau socket code d'enregistrement sur le fil:
Nouveau Serveur À L'Écoute De Code:
Il y avait une mise à jour de la structure du serveur/threads que je vais omettre. L'important est ici que le support dans lequel le paquet a été reçu avec a été ré-utilisé pour envoyer des données vers le client. En outre, le paquet a été ré-utilisé pour envoyer des données en arrière:
Voici les parties pertinentes de ma classe wrapper qui montre ce que chaque thread a été tenue:
OriginalL'auteur someone1
J'ai eu un problème similaire. Sur l'Android était à deux sockets (envoi/écoute), et sur un PC serveur a de nouveau été deux sockets (envoi/écoute). Le téléphone serait ping le PC est connu socket d'écoute avec l'adresse du téléphone inconnu socket d'écoute, de sorte que le PC pourrait répondre. Rien de ce que je faisais semble être d'obtenir l'adresse de la socket d'écoute, la prise en aurait jamais rien recevoir.
Cela a résolu mon problème: Android: java.net.DatagramSocket.lier: Invalid Argument Exception. Utiliser un canal de créer le socket, puis de liaison sur null. Maintenant, je peux utiliser l'envoi de prise sur le téléphone pour envoyer un paquet contenant le port de la socket d'écoute (les adresses ip sont les mêmes) pour le PC, obtenu avec
.getLocalPort()
Le PC lit le byte[], obtient le port, et envoie des paquets sur les téléphones port d'écoute.OriginalL'auteur Flynny75
android ont entrant pare-feu
vous devez utiliser la première udop perforatrice même chaussette objet avec minuterie
OriginalL'auteur rtdff