Translate

lunes, 30 de abril de 2012

Chat entre emuladores Android

Hola Androides,

Segundas partes nunca fueron buenas, pero aquí solo hacemos primeras partes. En las soluciones presentadas en la sección de aplicaciones hay presentado un Chat para móbiles Android que utiliza una conexión Wifi establecida. El problema viene cuando intentamos probar esta aplicación con un solo dispositivo. En este caso necesitaremos emuladores que intervengan como dialogantes del chat de pruebas. Cada emulador o dispositivo virtual se encuentra aislado de la computadora mediante un router virtual que se encuentra en una red privada 10.0.2/24 de la máquina virutal. De este modo nuestros emuladores no pueden de forma directa hablarse entre sí. En el caso de nuestro Broadcast Chat en la sección de ejercicios el dispositivo real envía un broadcast (paquete con IP de destino e.g. 192.168.1.255) a nuestra WIFI, para que esta repita a todos los dispositivos. El problema es que nuestro emulador no tiene WIFI y la redirección de puertos está limitada ya que cada emulador debe hablar a un puerto distinto de nuestro Localhost. Como solucionamos esto? Veamos algunas cosas.

  •  La red del emulador tiene la siguiente arquitectura:
The virtual router for each instance manages the 10.0.2/24 network address space — all addresses managed by the router are in the form of 10.0.2., where is a number. Addresses within this space are pre-allocated by the emulator/router as follows:

Network AddressDescription
10.0.2.1Router/gateway address
10.0.2.2Special alias to your host loopback interface (i.e., 127.0.0.1 on your development machine)
10.0.2.3First DNS server
10.0.2.4 / 10.0.2.5 / 10.0.2.6Optional second, third and fourth DNS server (if any)
10.0.2.15The emulated device's own network/ethernet interface
127.0.0.1The emulated device's own loopback interface

  • JAVA nos da las máximas fácilidades para crear un servidor escuchando en un solo puerto a varios clientes(Emuladores) con Sockets conectados a nuestra máquina de desarrollo (10.0.2.2) 
La solución es un servidor que emulará la función que hace nuestra WIFI cuando hacemos un BroadCast. Les presento a Android Emulator Server que se compone de dos ficheros: Main.Java y ServerService.Java. Recordad que este Servidor debe correr en vuestra máquina de desarrollo como aplicación JAVA y no como Android Application. Bora entao:




Main.Java



package EmulatorServer;

import java.io.IOException;

public class Main {

 /**
  * @param args
  * @throws IOException 
  */
 public static void main(String[] args) throws IOException {
  // TODO Auto-generated method stub
  new ServerService();
 
 }

}




ServerService.Java


package EmulatorServer;


import java.io.IOException;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Vector;

public class ServerService{
 
 private final int EMUPORT1 = 2560;
 private final int BCAST_PORT =2562;
 public static boolean Server_Serve=true;
 public static int N_Clients=0;
 Vector clients = new Vector();
 
 ServerSocket eSocket;
 
 
 
 ServerService() throws IOException{
  
  
  try {
   eSocket = new ServerSocket(EMUPORT1);
   listen();
   
  } catch (SocketException e) {
   // TODO Auto-generated catch block
   
   e.printStackTrace();
  }
 }
 
 public  synchronized void listen() throws IOException{
  while (true){
   
   
    
   Socket ClientSocket=null;
   try {
    ClientSocket = eSocket.accept();  
    if(Server_Serve || N_Clients>0) {
     N_Clients++;
     System.out.printf("Clientes: " + N_Clients +"\n");
     Server_Serve = false;
     System.out.printf(ClientSocket.getLocalSocketAddress().toString());  
     System.out.printf("Este es el punto final de este Socket\n");
     new ComServerThread(ClientSocket).start();
    }else break;
    
   } catch (IOException e) {
    // TODO Auto-generated catch block
    //System.out.print("Couldn't connect more clients");
    //e.printStackTrace();
   }
   
  
  }
 
 }
 
 public void broadcast(String message,ComServerThread ownclient) throws IOException{
  
  for(ComServerThread c:clients){
   if (!c.equals(ownclient))
    c.outToClient.writeObject(message);
    c.outToClient.flush();
  }
 }


class ComServerThread extends Thread{

private Socket ClientSocket;
ObjectInputStream infromClient = null;
ObjectOutputStream outToClient = null;

 ComServerThread(Socket ClientSocket){
  this.ClientSocket=ClientSocket;
  clients.add(this);
 
 }
 
  @Override

 public void run(){
  System.out.printf("Entro el Thread\n");
  String clientSentence;
  
      
  try {
  
   outToClient = new ObjectOutputStream(ClientSocket.getOutputStream());
   infromClient = new ObjectInputStream(ClientSocket.getInputStream());
  } catch (IOException e2) {
   // TODO Auto-generated catch block
   e2.printStackTrace();
  }
  while (ClientSocket.isConnected()){
  
     try {
     
      clientSentence = (String) infromClient.readObject();
      if (clientSentence.equals("Close")) break;
               if (clientSentence != null){
                System.out.printf("Llego aki :" + clientSentence + "\n");
                broadcast(clientSentence,this);
                //outToClient.writeObject(clientSentence);
                //outToClient.flush();
                }
     } catch (IOException e1) {
      // TODO Auto-generated catch block
      //e1.printStackTrace();
     } catch (ClassNotFoundException e) {
      // TODO Auto-generated catch block
      //e.printStackTrace();
     }
  
  }
  try {
   infromClient.close();
   outToClient.close();
   ClientSocket.close();
   ServerService.N_Clients--;
   System.out.printf("Clientes: " + ServerService.N_Clients + "\n");
   if (N_Clients == 0) {eSocket.close();System.out.println("Server Cerrado");}
   
   
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }

}
}

Para ver el codigo del cliente observe la clase EmuComThread en la sección de aplicaciones.

No hay comentarios: