Author Topic: Problemas para escuchar la respuesta del Servidor  (Read 3642 times)

nejagope

  • Newbie
  • *
  • Posts: 16
  • Karma: 0
    • View Profile
Problemas para escuchar la respuesta del Servidor
« on: Abril 27, 2014, 05:08:42 am »
Saludos Chuidiang! 

Gracias al tutorial de sockets que encontré en: http://www.chuidiang.com/clinux/sockets/sockets_simp.php pude comenzar mi aplicación cliente/servidor pero tengo un problems que no logro resolver. Estoy trabajando con dos aplicaciones distintas (en Qt)(una es el servidor, otra el cliente) Lo que sucede es que cuando el cliente manda un mensaje al servidor todo va bien y el servidor recibe el mensaje. Pero cuando intento que el sevidor responda la aplicación del cliente no recibe el mensaje y hasta se queda trabada. ¿Qué podrá estar mal?

Este es el código del servidor:
Code: [Select]
int Server::iniciarServidor(){
    /*
    * Descriptores de socket servidor y de socket con el cliente
    */
    int Socket_Servidor;
    int Socket_Cliente;
    char Cadena[100];
    /*
    * Se abre el socket servidor, con el servicio "cpp_java" dado de
    * alta en /etc/services.
    */
    Socket_Servidor = Abre_Socket_Inet ("cpp_java");
    if (Socket_Servidor == -1)
    {
        printf ("No se puede abrir socket servidor\n");
        return -1;
    }
 
    while(true){

    /*
    * Se espera un cliente que quiera conectarse
    */
        Socket_Cliente = Acepta_Conexion_Cliente (Socket_Servidor);
        if (Socket_Servidor == -1)
        {
            printf ("No se puede abrir socket de cliente\n");
            return -1;
        }

        /*
    * Se lee la informacion del cliente, suponiendo que va a enviar
    * 100 caracteres.
    */
        int bytesLeidos = Lee_Socket (Socket_Cliente, Cadena, 100);
        /*
    * Se escribe en pantalla la informacion que se ha recibido del
    * cliente
    */
        printf ("Soy Servior, he recibido : %s\n", Cadena);
     /*
    * Se prepara una cadena de texto para enviar al cliente. La longitud
    * de la cadena es 5 letras + \0 al final de la cadena = 6 caracteres
    */
        strcpy (Cadena, "Adios");

 
        Escribe_Socket (Socket_Cliente, Cadena, 6);

        /*
    * Se cierra el socket con el cliente
    */
        close (Socket_Cliente);

    }
    close (Socket_Servidor);

    return 0;
}

Y este es el código del cliente:
Code: [Select]
int Client::mandarMsjAlServidor(char* msj, int longitud){
    int socketConServidor = Abre_Conexion_Inet ("localhost", "cpp_java");
    if (socketConServidor == 1)
    {
        printf ("No puedo establecer conexion con el servidor\n");
        return -1;
    }

    char Cadena[100];
    strcpy (Cadena, msj);

    Escribe_Socket (socketConServidor, Cadena, longitud);

    Lee_Socket (socketConServidor, Cadena, 6);
 
    printf ("Soy cliente, He recibido : %s\n", Cadena);
    close (socketConServidor);
    return Cadena;
}

Gracias de antemano por la ayuda.

chuidiang

  • Administrator
  • Hero Member
  • *****
  • Posts: 5472
  • Karma: 12
    • View Profile
    • Apuntes de programación
Re: Problemas para escuchar la respuesta del Servidor
« Reply #1 on: Abril 27, 2014, 12:18:19 pm »
Si se envía y se cierra el socket inmediatamente, que es lo que está haciendo el servidor al responder, puede que el mensaje no llegue al cliente y se quede indefinidamente leyendo.

Para evitarlo, a la hora de abrir el socket hay que poner la opción SO_LINGER con un tiempo adecuado. Este tiempo en esta opción es el tiempo que se espera a que todos los mensajes hayan terminado de entregarse antes de cerrar realmente el socket. http://alas.matf.bg.ac.rs/manuals/lspe/snode=105.html

Se bueno.

nejagope

  • Newbie
  • *
  • Posts: 16
  • Karma: 0
    • View Profile
Re: Problemas para escuchar la respuesta del Servidor
« Reply #2 on: Mayo 01, 2014, 09:32:30 pm »
gracias por la ayuda Chuidiang, lamentablemente continúa el problema, utilicé la función LINGER así:
Code: [Select]
int Server::iniciarServidor(){
 
    int Socket_Servidor;
    int Socket_Cliente;
    char Cadena[100];

    /*
    * Se abre el socket servidor, con el servicio "cpp_java" dado de
    * alta en /etc/services.
    */
    Socket_Servidor = Abre_Socket_Unix( "cpp_java");

    if (Socket_Servidor == -1)
    {
        printf ("No se puede abrir socket servidor\n");
        return -1;
    }
 
    while(true){
        Socket_Cliente = Acepta_Conexion_Cliente (Socket_Servidor);

        int z;               
        struct linger so_linger;

        so_linger.l_onoff = 1;
        so_linger.l_linger = 10;
        z = setsockopt(Socket_Cliente,
            SOL_SOCKET,
            SO_LINGER,
            &so_linger,
            sizeof so_linger);

        if ( z )
            perror("setsockopt(2)");
     
        if (Socket_Cliente == -1)
        {
            printf ("No se puede abrir socket de cliente\n");
            return -1;
        }else{
            printf ("el cliente se ha conectado\n");
        }

        int bytesLeidos = Lee_Socket (Socket_Cliente, Cadena, 100);
if (bytesLeidos>0)
            printf ("el servidor ha leido el mensaje");

    /*
    * Se emite una señal que se usará para mostrar  la informacion que se ha recibido del
    * cliente en el textEdit de la ventana
    */
        QString *a = new QString(Cadena);
        emit setMsj("Soy Servior, he recibido :  "+ *a);

    /*
    * Se prepara una cadena de texto para enviar al cliente. La longitud
    * de la cadena es 5 letras + \0 al final de la cadena = 6 caracteres
    */
        char respuesta[6];

        strcpy (respuesta, "Adios");

        emit setMsj ("en la siguiente linea voy a mandar el mensaje al cliente");
        Escribe_Socket (Socket_Cliente, respuesta, 6);

        printf ("he dicho ADIOS al cliente");

        close (Socket_Cliente);
   
    close (Socket_Servidor);

    return 0;
}

Algo que me parece relevante es el hecho de que el servidor muestra el mensaje (que imprimo con printf) que dice que "el ciente se ha conectado",
pero el mensaje donde digo "he dicho ADIOS al cliente" no se muestra hasta que cierro la ventana del cliente, en general cualquier printf que uso luego de leer el socket del cliente ya no aparece hasta que cierro la ventana del cliente.

También me parece importante mencionar que cuando la comunicación es en una sola vía (el cliente manda un mensaje al servidor, pero el cliente no lee ninguna respuesta) la aplicación funciona a la perfección y sólo se queda trabada si el cliente no cierra el socket con el servidor.

chuidiang

  • Administrator
  • Hero Member
  • *****
  • Posts: 5472
  • Karma: 12
    • View Profile
    • Apuntes de programación
Re: Problemas para escuchar la respuesta del Servidor
« Reply #3 on: Mayo 02, 2014, 12:22:29 am »
"pero el mensaje donde digo "he dicho ADIOS al cliente" no se muestra hasta que cierro la ventana del cliente, en general cualquier printf que uso luego de leer el socket del cliente ya no aparece hasta que cierro la ventana del cliente"

Lo de "he dicho adios .." es después de escribir. Dices que en general no sale el texto después de leer. ¿Te ocurre tanto al leer como al escribir?.

Al leer puede tener sentido si el cliente no escribe todo lo que el servidor intenta leer, la lectura del servidor se puede quedar bloqueada esperando datos y al cerrar el cliente, ¿se cierra el socket? y el servidor sale de la lectura. Al escribir tiene menos sentido, ya que se escribe independiemente de que el cliente lea o no y la escritura no se suele quedar bloqueada, salvo que intentes escribir muuuuchos bytes y el cliente no los lea.

Se bueno.

nejagope

  • Newbie
  • *
  • Posts: 16
  • Karma: 0
    • View Profile
Re: Problemas para escuchar la respuesta del Servidor
« Reply #4 on: Mayo 02, 2014, 01:18:05 am »
Gracias chuidiang
Quote
Lo de "he dicho adios .." es después de escribir. Dices que en general no sale el texto después de leer. ¿Te ocurre tanto al leer como al escribir?.
justo eso que mencionas es lo que me inquieta. Sin escribir mucho código explicaré lo que ocurre:

1er caso (cuando el cliente no hace la lectura del socket con el servidor, sino que solo escribe en él):
Cuando hago esto el Servidor lee el socket del cliente y lo muestra en pantalla el mensaje del cliente sin ningún problema.
Y el mensaje del servidor "he dicho ADIOS..." también se despliega, eso me indica que el método llegó a su final exitosamente.

2do caso (cuando el cliente escribe en el socket con el servidor y luego lo lee):
Cuando agrego esta línea de código en el cliente, inmediatamente después de la línea donde escribe en el socket, surge el problema:
Lee_Socket (Socket_Con_Servidor, Cadena, 6);

Cuado hago esto el servidor ni siquiera hace la lectura del socket el único mensaje que despliega el servidor es que el cliente se ha conectado,
pero no muestra el mensaje que le mandó el cliente y mucho menos muestra la línea donde dice "ADIOS". Y la ventana del cliente se queda trabada.





chuidiang

  • Administrator
  • Hero Member
  • *****
  • Posts: 5472
  • Karma: 12
    • View Profile
    • Apuntes de programación
Re: Problemas para escuchar la respuesta del Servidor
« Reply #5 on: Mayo 02, 2014, 05:20:10 am »
Veo métodos Lee_socket de 100, pero no veo ningún escirbe de 100, quizás venga por ahí el problema. El método Lee_socket está pensado para leer exactamente los bytes que se le dicen, es decir, 100 y se queda bloqueado hasta que llegan 100.

Se bueno.

nejagope

  • Newbie
  • *
  • Posts: 16
  • Karma: 0
    • View Profile
Re: Problemas para escuchar la respuesta del Servidor
« Reply #6 on: Mayo 03, 2014, 08:34:25 am »
Esa resultó ser la solución. Gracias por la ayuda Chuidiang!  ;D ;D

 

ey