|
||
|
|
|
|||||||
| Programación y Desarrollo para Android Subforo exclusivo para temas de programación de software para PDAs y desarrollo de aplicaciones, interfaces, etc bajo Android |
![]() |
|
|
Herramientas |
|
#1
|
||||
|
||||
|
Error sockets entre server y cliente en android.
Buenas.
Intento establecer conexion entre un servidor creado en java Netbeans, en lineas generales en la clase del servidor: Código:
ServerSocket server = new ServerSocket(puerto); //puerto = 30922;
while (true){
Socket client = server.accept();
System.out.println("Aceptado desde :"+client.getInetAddress());
ChatHandler c = new ChatHandler(client);
c.start();
}
Código:
public ChatHandler (Socket s) throws IOException{
this.s=s;
in = new DataInputStream(new BufferedInputStream(s.getInputStream()));
out = new DataOutputStream ( new BufferedOutputStream(s.getOutputStream()));
}
Código:
String ip = "192.168.1.2";
int puerto = 30922;
Log.v(this.getClass().getClass().getCanonicalName(), "Socket " + ip + " " + puerto);
try {
sk = new Socket(ip, puerto);
Log.v(getClass().getCanonicalName(), "Se ha iniciado conexion...");
Log("Conexion con servidor: "+ip+" Puerto: "+puerto);
entrada = new DataInputStream(new BufferedInputStream(sk.getInputStream()));
salida = new DataOutputStream(new BufferedOutputStream(sk.getOutputStream()));
} catch (UnknownHostException e) {
e.printStackTrace();
salidaTxt.append(e.getMessage());
} catch (IOException e) {
e.printStackTrace();
salidaTxt.append(e.getMessage());
}
Pero me salta la exception con error de conexion. Supongo que sera por las ips , pero no logro dar con ello. Lo estoy haciendo con el avd de eclipse y supongo que la ip que tendre que poner "192.168.1.2" es la ip donde esta el pc? ando un poco perdido. Un saludo. |
|
|
|
#2
|
||||
|
||||
|
Si, deberas meterle la ip de tu pc y el puerto por el que se comunican. Y fijate qe este corriendo el servidor antes de iniciar el cliente. Tambien comprueba que el avd te conecta a internet.
Pero creo qe el fallo esta en el servidoe porque no habre correctamente los sockets. Has comprobado si te salta errores en el servidor???
__________________
Controlador de Medicamentos 1.5 (https://play.google.com/store/apps/d...mentcontrolled)
Legislación Basica Española 1.1 (https://play.google.com/store/apps/d...islacionbasica) |
|
#3
|
||||
|
||||
|
Hola.
El avd lo tengo conectado a internet porque he probado a abrir navegador en el avd y funciona. El puerto esta abierto y la ip es la del pc. El servidor esta corriendo lo abro desde netbeans pero no se si abre correctamente los sockets ya que el error salta cuando ejecuto la aplicacion cliente desde eclipse. trazas: Código:
12-28 11:45:53.281: E/AndroidRuntime(840): FATAL EXCEPTION: main
12-28 11:45:53.281: E/AndroidRuntime(840): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.socketclientprueba/com.example.socketclientprueba.SocketCliente}: android.os.NetworkOnMainThreadException
12-28 11:45:53.281: E/AndroidRuntime(840): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
12-28 11:45:53.281: E/AndroidRuntime(840): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
12-28 11:45:53.281: E/AndroidRuntime(840): at android.app.ActivityThread.access$600(ActivityThread.java:141)
12-28 11:45:53.281: E/AndroidRuntime(840): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
12-28 11:45:53.281: E/AndroidRuntime(840): at android.os.Handler.dispatchMessage(Handler.java:99)
12-28 11:45:53.281: E/AndroidRuntime(840): at android.os.Looper.loop(Looper.java:137)
12-28 11:45:53.281: E/AndroidRuntime(840): at android.app.ActivityThread.main(ActivityThread.java:5041)
12-28 11:45:53.281: E/AndroidRuntime(840): at java.lang.reflect.Method.invokeNative(Native Method)
12-28 11:45:53.281: E/AndroidRuntime(840): at java.lang.reflect.Method.invoke(Method.java:511)
12-28 11:45:53.281: E/AndroidRuntime(840): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
12-28 11:45:53.281: E/AndroidRuntime(840): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
12-28 11:45:53.281: E/AndroidRuntime(840): at dalvik.system.NativeStart.main(Native Method)
12-28 11:45:53.281: E/AndroidRuntime(840): Caused by: android.os.NetworkOnMainThreadException
12-28 11:45:53.281: E/AndroidRuntime(840): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1117)
12-28 11:45:53.281: E/AndroidRuntime(840): at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:84)
12-28 11:45:53.281: E/AndroidRuntime(840): at libcore.io.IoBridge.connectErrno(IoBridge.java:127)
12-28 11:45:53.281: E/AndroidRuntime(840): at libcore.io.IoBridge.connect(IoBridge.java:112)
12-28 11:45:53.281: E/AndroidRuntime(840): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
12-28 11:45:53.281: E/AndroidRuntime(840): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
12-28 11:45:53.281: E/AndroidRuntime(840): at java.net.Socket.startupSocket(Socket.java:566)
12-28 11:45:53.281: E/AndroidRuntime(840): at java.net.Socket.tryAllAddresses(Socket.java:127)
12-28 11:45:53.281: E/AndroidRuntime(840): at java.net.Socket.<init>(Socket.java:177)
12-28 11:45:53.281: E/AndroidRuntime(840): at java.net.Socket.<init>(Socket.java:149)
12-28 11:45:53.281: E/AndroidRuntime(840): at com.example.socketclientprueba.SocketCliente.onCreate(SocketCliente.java:72)
12-28 11:45:53.281: E/AndroidRuntime(840): at android.app.Activity.performCreate(Activity.java:5104)
12-28 11:45:53.281: E/AndroidRuntime(840): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
12-28 11:45:53.281: E/AndroidRuntime(840): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
12-28 11:45:53.281: E/AndroidRuntime(840): ... 11 more
|
|
#4
|
||||
|
||||
|
Mmmm tienes el permiso de internet en la aplicacion? Supongo que si.
Mete el hilo del cliente en un servicio, de esta forma no te dara problemas, y utilizar el IBinder para comunicarlo con la actividad. Espero que sirva de ayuda.
__________________
Controlador de Medicamentos 1.5 (https://play.google.com/store/apps/d...mentcontrolled)
Legislación Basica Española 1.1 (https://play.google.com/store/apps/d...islacionbasica) |
|
#5
|
||||
|
||||
|
Trabajo asíncrono con red -> hilo aparte. Ponlo en un Thread o en el doInBackground de un AsyncTask y no reventará.
@jtsamper: meter el código en un service sólo para eso es un poco matar moscas a cañonazos, a no ser que tenga que estar funcionando incluso si la app no o que tenga que compartirse en varias activities. Además, si no recuerdo mal, el código de un service sigue ejecutándose en el hilo principal (al menos si está en un proceso aparte). Un saludo. Última edición por Arasthel Día 28/12/13 a las 13:35:49. |
| Gracias de parte de: | ||
|
#6
|
||||
|
||||
|
Buenas.
Si, tengo puesto el permiso de internet en el Manifest: <uses-permission android:name="android.permission.INTERNET"/> Y aunque no lo haya puesto en el código, tambien esta creado un hilo aparte para recoger mensaje desde DataInputStream El codigo del OnCreate del cliente: Código:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_socket_cliente);
texto = (EditText) findViewById(R.id.EditText01);
salidaTxt = (TextView) findViewById(R.id.TextView01);
contador = (TextView) findViewById(R.id.textView1);
btnEnviar = (Button) findViewById(R.id.button1);
btnEnviar.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Log.v(getClass().getCanonicalName(), "Iniciando Socket...");
Log("Enviando... " + texto.getText().toString() + "\n");
ejecutaClienteSocket();
}
});
String ip = "192.168.1.2";
int puerto = 30922;
Log.v(this.getClass().getClass().getCanonicalName(), "Socket " + ip + " " + puerto);
try {
sk = new Socket(ip, puerto);
Log.v(getClass().getCanonicalName(), "Se ha iniciado conexion...");
Log("Conexion con servidor: "+ip+" Puerto: "+puerto);
entrada = new DataInputStream(new BufferedInputStream(sk.getInputStream()));
salida = new DataOutputStream(new BufferedOutputStream(sk.getOutputStream()));
} catch (UnknownHostException e) {
e.printStackTrace();
salidaTxt.append(e.getMessage());
} catch (IOException e) {
e.printStackTrace();
salidaTxt.append(e.getMessage());
}
final Handler myHandler = new Handler();
(new Thread(new Runnable() {
public void run() {
while (true) {
String recibe;
try {
recibe = getEntrada().readUTF();
if (recibe != null) {
SocketCliente.this.setMsg(recibe);
Log.v(getClass().getCanonicalName(), "Recibiendo datos.." + recibe);
}
}catch (IOException e) {
e.printStackTrace();
}
myHandler.post(new Runnable() {
public void run() {
actualizarMensajes();
}
});
}
}
})).start();
Log.v(getClass().getCanonicalName(), "Terminando de iniciar componentes");
}
Da la impresion de que es un error de conexion de sockets , no? |
|
#7
|
||||
|
||||
|
La creación del socket la haces fuera del hilo, y tiene toda la pinta de ser eso lo que da fallo (al menos según el logcat). ¿Qué línea es la 72 en tu código?
Cita:12-28 11:45:53.281: E/AndroidRuntime(840): at com.example.socketclientprueba.SocketCliente.onCre ate(SocketCliente.java:72)
![]() |
|
#8
|
||||
|
||||
|
Como dice Arasthel, la creación de la conexión la haces en el hilo principal, y eso también hace uso de Internet (por eso el UnknownHostException). Hasta tal punto que es lo que más bloqueante puede ser (resolver el host, el host está caido, etc).
También debe hacerse fuera del hilo principal. |
|
#9
|
||||
|
||||
|
Hola de nuevo.
La linea 72 es efectivamente la creacion del socket: sk = new Socket(ip, puerto); Pero poniendo la creacion de la conexion try { sk = new Socket(ip, puerto); Log.v(getClass().getCanonicalName(), "Se ha iniciado conexion..."); Log("Conexion con servidor: "+ip+" Puerto: "+puerto); entrada = new DataInputStream(new BufferedInputStream(sk.getInputStream())); salida = new DataOutputStream(new BufferedOutputStream(sk.getOutputStream())); } catch (UnknownHostException e) { e.printStackTrace(); salidaTxt.append(e.getMessage()); } catch (IOException e) { e.printStackTrace(); salidaTxt.append(e.getMessage()); } dentro del Thread tampoco funciona y da el mismo error. Pero pasa lo siguiente: Usando un device virtual basado en Android 2.3.3 si que funciona y se establece conexion pero usando un 4.2.2 no funciona. Ni poniendo la conexion dentro ni fuera del Thread. Que puede haber que funcione en 2.3.3 y no en 4.2.2?? No he probado con demas versiones android. Alguna idea? Última edición por manolazo Día 29/12/13 a las 13:00:49. |
|
#10
|
||||
|
||||
|
La NetworkOnMainThreadException es una excepción que ocurre sólo a partir de Android 3.0 y que sale porque algo que hace uso de red está en el hilo principal, así que algo tiene que haberse quedado fuera del Thread que hace uso del socket o de alguna forma de conexión. Mira el logcat, busca qué línea te dice de tu clase que está fallando (antes era la 72) y ponlo en un hilo aparte.
EDIT: ¿puedes poner el log y también el código tal y como está, a ver si por fin vemos dónde falla esto? Un saludo. Última edición por Arasthel Día 29/12/13 a las 13:11:45. |
|
#11
|
||||
|
||||
|
Trabajo asíncrono con red -> hilo aparte. Ponlo en un Thread o en el doInBackground de un AsyncTask y no reventará.
@jtsamper: meter el código en un service sólo para eso es un poco matar moscas a cañonazos, a no ser que tenga que estar funcionando incluso si la app no o que tenga que compartirse en varias activities. Además, si no recuerdo mal, el código de un service sigue ejecutándose en el hilo principal (al menos si está en un proceso aparte). Un saludo. ![]() Supongo que para caso habrá lo suyo, pero el service me congelaba una activity y el intentservice no
__________________
|
|
#12
|
||||
|
||||
|
La NetworkOnMainThreadException es una excepción que ocurre sólo a partir de Android 3.0 y que sale porque algo que hace uso de red está en el hilo principal, así que algo tiene que haberse quedado fuera del Thread que hace uso del socket o de alguna forma de conexión. Mira el logcat, busca qué línea te dice de tu clase que está fallando (antes era la 72) y ponlo en un hilo aparte.
EDIT: ¿puedes poner el log y también el código tal y como está, a ver si por fin vemos dónde falla esto? Un saludo. ![]() Un a vez puesto todo el un hilo aparte el problema era que dentro dle propio hilo tenia una llamada a Log("Conexion con servidor: "+ip+" Puerto: "+puerto); donde la funcion Log pintaba un textview y eso solo se puede hacer dentro de hilo principal con lo cual usando un handler se soluciona. Una cuenstion mas. En caso de querer usar para depurar la aplicación en un dispositivo real, habira que poner la ip de mi conexion a internet en vez del localhost? Un servidor apache? Un saludo. |
|
#13
|
||||
|
||||
|
Claro, tendrías que poner la IP del servidor en el que esté, si está en tu propio PC sería la IP externa de tu red. Si quieres que se quede fija, que probablemente será dinámica la que tengas contratada, puedes hacer uso de dyndns o algo parecido para tener una "url" que apunte a tu server.
Un saludo. |
|
#14
|
||||
|
||||
|
Trabajo asíncrono con red -> hilo aparte. Ponlo en un Thread o en el doInBackground de un AsyncTask y no reventará.
@jtsamper: meter el código en un service sólo para eso es un poco matar moscas a cañonazos, a no ser que tenga que estar funcionando incluso si la app no o que tenga que compartirse en varias activities. Además, si no recuerdo mal, el código de un service sigue ejecutándose en el hilo principal (al menos si está en un proceso aparte). Un saludo. ![]() de hay que le dijera de meterlo en un service.
__________________
Controlador de Medicamentos 1.5 (https://play.google.com/store/apps/d...mentcontrolled)
Legislación Basica Española 1.1 (https://play.google.com/store/apps/d...islacionbasica) |
|
#15
|
||||
|
||||
|
|
#16
|
||||
|
||||
|
Hola, muchas gracias por la ayuda.
Hay una cosa que no me queda clara del codigo a ver si me la podeis explicar. Código:
public class ChatServer {
public ChatServer (int port) throws IOException{
ServerSocket server = new ServerSocket(port);
while (true){
Socket client = server.accept();
System.out.println("Aceptado desde :"+client.getInetAddress());
ChatHandler c = new ChatHandler(client);
c.start();
}
}
public static void main (String args[]) throws IOException {
new ChatServer(30922);
}
}
No es un bucle en donde se repita la sentencia interna verdad? es decir , si pones un contador o un system.out.prinltn("lo que sea"); no se ejecuta indefinidamente, cuando en este tipo de bucles ha de repetirse indefinidamente hasta que no se cumpla la condicion. Se supone que ese while es para quedarse indefinidamente a la escucha de aceptar conexiones pero no lo entiendo muy bien. |
|
#17
|
||||
|
||||
|
"server.accept()" es bloqueante, es decir, se quedará ahí hasta que llegue una nueva solicitud de conexión por parte de un cliente.
Es algo muy común cuando se programa un servidor de sockets. |
|
#18
|
||||
|
||||
|
OK, no lo sabia.
Gracias. Edito: En este caso tambien es bloqueante la lectura de un dataInputStream para la lectura de datos verdad? Código:
DataInputStream in = new DataInputStream(s.getInputStream());
while (true){
String sMensaje = in.readUTF();
ventana.mensajeRecibido(sMensaje);
}
Última edición por manolazo Día 02/01/14 a las 14:13:31. |
![]() |
Estás aquí
|
||||||
|
||||||