Bennu Game Development

Foros en Español => General => Topic started by: darío on June 20, 2016, 01:49:04 PM

Title: Diversos problemas con mod_fsock y conexiones UDP
Post by: darío on June 20, 2016, 01:49:04 PM
Llevo un par de días intentando entender cómo hacer funcionar mod_fsock para conexiones UDP de un modo correcto y tengo varios problemas. Todos los ejemplos que he visto de uso de la mod_fsock hacen uso de TCP y he intentado leer todo lo posible tanto en la web, como en un "leeme.txt" que acompaña a la mod_fsock así como el propio código de la mod_fsock.

Estoy usando Linux y compilando con PixTudio.

1. El tema del bloqueo (fsock_setblock) que consido solucionar si modifico libsocket.c como ya he expuesto en mi tema anterior.

2. udpsock_recv devuelve siempre -1. Leyendo el código de libsocket.c entiendo que en Linux el valor devuelto se corresponde con recvfrom. En teoría un valor de -1 indicaría que ha habido algún problema, pero sin embargo los datos si que parecen ser recibidos!

3. No entiendo el valor devuelto por udpsock_recv en los dos últimos parámetros:


    char bytes[0];
    unsigned short port;
    unsigned int ip_address;



            received_bytes = udpsock_recv ( socket,
                &bytes,
                1,
                &ip_address,
                &port );


Entiendo que esto viene de:

int libsocket_recv_udp(int socket, void *dest, size_t len, int *ip, int *port) {
    struct sockaddr_in connection_info;
    int received_bytes;
#ifdef WIN32
    int connection_info_size;
#else
    unsigned int connection_info_size;
#endif

    received_bytes =
        recvfrom(socket, dest, len, 0, (SOCKADDR *)&connection_info, &connection_info_size);

    if (socket != -1) {
        *ip   = connection_info.sin_addr.s_addr; // ip
        *port = ntohs(connection_info.sin_port); // puerto
    }

    return received_bytes;
}


Pero no entiendo por qué siempre recibo una dirección IP que no tiene nada que ver con ninguna de las IPs de mi ordenador, ni el puerto tiene nada que ver con el puerto que he habilitado para establecer la comunicación.

Adjunto un video donde se muestra tanto el problema #2 como el problema #3. La ventana de consola de arriba a la derecha es una sesión en una raspberry local que tengo en mi red, y como véis, la información enviada por UDP es correctamente recibida en mi juego. La ventana de abajo a la derecha es un programa en Mono corriendo localmente, y también cuando envío un byte por ahí lo recibo en mi juego, pero no entiendo la IP que se muestra ni tampoco el puerto que se muestra, ya que en teoría yo estoy trabajando sobre el puerto 11000.

Mi código, después de un fsock_init:


Const
    _MULTIPLAYER_RECEIVE_INTERVAL = 300; // 1/100 s
    _MULTIPLAYER_TIMER_RECEIVE = 0;
End
Process multiplayer_receiver ()
Private
    int socket;
   
    char bytes[0];
    unsigned short port;
    unsigned int ip_address;
   
    int received_bytes;
    int n;
    string ip_text;
End
Begin
    socket = udpsock_open ();
    //say ( "Result setblock: " + fsock_setblock ( socket, 0 ) );
    fsock_bind ( socket, 11000 );
     
    timer [ _MULTIPLAYER_TIMER_RECEIVE ] = 0;
   
    Loop
        If ( timer[ _MULTIPLAYER_TIMER_RECEIVE ]
                > _MULTIPLAYER_RECEIVE_INTERVAL )
           
            ip_text = "";
            received_bytes = 0;
            bytes[0] = 0;
            port = 0;
            ip_address = 0;
           
            received_bytes = udpsock_recv ( socket,
                &bytes,
                1,
                &ip_address,
                &port );
           
            say ( "Received: " + received_bytes );
            say ( "Address: ");
            From n=0 To 3;
                ip_text += itoa( ( ip_address & (255 << n * 8) ) >> ( n * 8 ) ) + ".";
            End
            say ( "IP: " + ip_text );
            say ( "Port: " + port );
            say ( "Byte 0: " + bytes[0]);
           
            If ( received_bytes > 0 )
                // multiplayer_process_receive_frame ( &bytes );
            End
           
            say ("");
           
            timer[ _MULTIPLAYER_TIMER_RECEIVE ] = 0;
        End
       
        Frame;
    End

OnExit:
    fsock_close(socket);
End


A ver si alguien me puede echar una mano... Muchas gracias...
Title: Re:Diversos problemas con mod_fsock y conexiones UDP
Post by: panreyes on June 20, 2016, 01:54:11 PM
Lo de la IP que no corresponde, lo desconozco. ¿Es posible que esté invertida?

Por otro lado, quizás lo del puerto esté relacionado con que sea el puerto de salida. El puerto de entrada tiene que ser el 11000, pero el de salida puede ser cualquiera aleatorio.
Title: Re:Diversos problemas con mod_fsock y conexiones UDP
Post by: darío on June 20, 2016, 02:05:53 PM
No, eso ya lo había pensado, pero no está invertida. En cualquier caso creo que la función no debería devolver -1. Voy a ver si puedo investigar más... Estoy leyendo la documentación de recvfrom, pero parece que puede depender de la plataforma...

Lo del puerto, reconozco que no tengo mucha experiencia con conexiones sockets, para que sirve que dicha función devuelva el "puerto de salida"?
Title: Re:Diversos problemas con mod_fsock y conexiones UDP
Post by: darío on June 20, 2016, 02:34:13 PM
He probado a hacer un say() de fsock_errno y devuelve 22.

De acuerdo a http://www.virtsync.com/c-error-codes-include-errno (http://www.virtsync.com/c-error-codes-include-errno) significa EINVAL.

He visto también que con mi fix para fsock_setblock, recibo un 11 cuando no envío ningún paquete, que significa EWOULDBLOCK = EAGAIN, y de acuerdo a la documentación de recvfrom es correcto.

Sigo investigando...
Title: Re:Diversos problemas con mod_fsock y conexiones UDP
Post by: darío on June 20, 2016, 02:38:31 PM
He encontrado el bug!

De acuerdo con http://stackoverflow.com/questions/2999639/recvfrom-returns-invalid-argument-when-from-is-passed (http://stackoverflow.com/questions/2999639/recvfrom-returns-invalid-argument-when-from-is-passed), el parámetro connection_info_size de recvfrom tiene que ser inicializado a size_of (connection_info)!

Haciendo esto el programa funciona sin problemas!

Ahora haré un pull-request al repo de PixStuio para que lo podáis probar.

:)

Title: Re:Diversos problemas con mod_fsock y conexiones UDP
Post by: darío on June 20, 2016, 02:39:01 PM
Notese que el mismo problema aplica  a BennuGd...
Title: Re:Diversos problemas con mod_fsock y conexiones UDP
Post by: darío on June 20, 2016, 02:42:34 PM
La única linea cambiada es la de connection_info_size, que ahora se inizializa a sizeof(connection_info).


int libsocket_recv_udp(int socket, void *dest, size_t len, int *ip, int *port) {
    struct sockaddr_in connection_info;
    int received_bytes;
#ifdef WIN32
    int connection_info_size;
#else
    unsigned int connection_info_size = sizeof(connection_info);
#endif

    received_bytes =
        recvfrom(socket, dest, len, 0, (SOCKADDR *)&connection_info, &connection_info_size);

    if (socket != -1) {
        *ip   = connection_info.sin_addr.s_addr; // ip
        *port = ntohs(connection_info.sin_port); // puerto
    }

    return received_bytes;
}

Title: Re:Diversos problemas con mod_fsock y conexiones UDP
Post by: josebita on June 20, 2016, 03:09:25 PM
Mil gracias, darío :)
Tu cambio ya está en el repositorio de PixTudio.
Title: Re:Diversos problemas con mod_fsock y conexiones UDP
Post by: darío on June 20, 2016, 03:14:13 PM
Yeahh después de todo el día investigando esto ahora sí que me siento realizado!

8)