He leído muchas publicaciones en este sitio sobre cómo recibir paquetes UDP en Android. Sin embargo, ¡nada de esto me funciona!Android UDP Comunicación
Algunos conceptos básicos:
estoy probando en mi HTC Incredible (Android 2.2) que se ejecutan en 3G (no wifi o cualquier otra cosa). No hay emuladores involucrados aquí.
Mi código es simple:
- Mi servidor (que funciona en mi PC) escucha el tráfico UDP en el puerto 8752.
- Mi aplicación Android abre una DatagramSocket en un puerto aleatorio y envía un paquete a mi servidor con este puerto.
- Guardo esta información (el InetAddress forma el paquete recibido y el puerto que se encuentra dentro del paquete).
- Intento enviar un paquete UDP desde mi servidor (nuevamente, en mi PC) a mi aplicación de Android (ejecutándose en mi teléfono) y NO funciona.
//Server code to initialize the UDP socket (snippet)
public void init() {
datagram_server_socket = new DatagramSocket(port,local_addr);
datagram_server_socket.setSoTimeout(1000);
}
// fragmento de código en el Android APP que envía un paquete al servidor
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();
}
}
}
Ahora he duro codificado el puerto mi aplicación usa 8000. Sin embargo, lo extraño es que TODO EL TIEMPO pruebo mi programa (y veo la IP/Puerto que está guardado en mi servidor), el puerto del paquete procede de siempre es 33081. Tengo aa hilo escucha constante para el tráfico UDP en mi Android App pero el código no se ejecuta nunca superado la "recepción (paquetes)" parte:
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.");
}
}
}
¿Alguien ve un problema en mi código? ¿O hay algunos permisos/configuraciones que debo configurar primero en mi aplicación? Tengo habilitada la comunicación por internet.
Ejemplo de salida (a través del puerto del paquete getPort()):
Android App - Ahora escucha para el tráfico UDP en el puerto 8000
Android App - Envío de paquetes al servidor
Servidor - Paquete recibido de XXXXXX: 33081
Servidor - Envío de paquete IDLE a XXXXXX: 33081
Ejemplo de salida (a través del puerto de los datos del paquete):
Android App - Ahora escucha para el tráfico UDP en el puerto 8000
Android App - Envío de paquetes al servidor
Servidor - paquete recibido desde XXXXXX: 8000
servidor - Envío de paquetes IDLE para XXXXXX: 8000
La aplicación Android nunca recibe tráfico UDP de ninguno de los puertos.
¿Se puede conseguir esto para el trabajo en dos computadoras de escritorio/portátiles (sin su teléfono Android)? Si puede eliminar el teléfono como problema, entonces podemos suponer que es un problema con su código. – Kiril
Pude poner mi teléfono en mi red WiFi y obtener los paquetes UDP trabajando de esa manera (usando la dirección IP directa a mi máquina ya que el nombre de host, usando el nombre DNS externo NO funcionó). También hice que mi amigo probara un programa que escribí para simular las llamadas a la red de aplicaciones de Android en su casa (usando el nombre DNS externo) y funcionó bien (después de hacer un reenvío de puertos y forzar un puerto UDP no aleatorio). Espero que esto aclare que el problema es mi código. – someone1