none
Problema con Socket UDP y ReceiveFromAsync RRS feed

  • Pregunta

  • Hola a todos.

    No sé qué estoy haciendo mal, pero no consigo hacer que funcione. Estoy realizando un test de STUN sobre un servidor para ver temas de NAT y eso. Para el que no lo sepa, la idea es enviar una serie de paquetes UDP y esperar respuesta del servidor y dependiendo de esa respuesta enviar uno u otro paquete diferente.

    Pero el problema no está ahí. El problema está en que envío paquetes pero no recibo ninguno, o más bien sí que los recibo pero fuera de tiempo. Lo explico abajo. El código está tomado de internet, pero traducido a código Windows Phone, y el original funciona perfectamente. Básicamente lo encontrado usa Poll() y Receive() para enviar los datos y yo tengo que hacer un ReceiveFromAsync() por narices porque los otros dos métodos no están disponibles en WP.

    El método que envía es:

    public bool SendBytes()
    {
        var isOk = false;
        var sendEventArgs = new SocketAsyncEventArgs();
    
        try
        {
            sendEventArgs.SetBuffer(m_bytes, 0, m_bytes.Length);
            sendEventArgs.RemoteEndPoint = m_ipEndPoint;
            sendEventArgs.Completed += (sender, e) =>
                {
                    if (e.SocketError == SocketError.Success)
                        isOk = true;
                    m_event.Set();
                };
            m_event.Reset();
            m_socket.SendToAsync(sendEventArgs);
    
            m_event.WaitOne(k_maxWait);
        }
        catch{}
        finally
        {
            sendEventArgs.Dispose();
        }
    
        return isOk;
    }
    

    Y el que recibe:

    public bool ReceiveBytes()
    {
        var isOk = false;
        var recvEventArgs = new SocketAsyncEventArgs();
    
        try
        {
            recvEventArgs.SetBuffer(BytesReceived, 0, BytesReceived.Length);
            recvEventArgs.RemoteEndPoint = m_ipEndPoint;
            recvEventArgs.Completed += (sender, e) =>
                {
                    if (e.SocketError == SocketError.Success)
                        isOk = true;
                    m_event.Set();
                };
            m_event.Reset();
            if (m_socket.ReceiveFromAsync(recvEventArgs))
                m_event.WaitOne(1000);
            else
                isOk = true;
        }
        catch{}
        finally
        {
            recvEventArgs.Dispose();
        }
        return isOk;
    }
    

    El código es tremendamente sencillo. Un evento, la llamada y la espera a que transcurra la respuesta o un timeot. El buffer se instala él mismo y es consultado dependiendo de lo que retorne la recepción.

    El problema está en que cuando recibo respuesta del servidor, que no es siempre, no se dispara el evento de recepción (el lambda). Más bien, si hago eso en bucle, los eventos, pese a haber llamado al Dispose() del SocketAsyncEventArgs(), se me disparan luego, al cabo incluso de varios minutos, cuando ya no me hacen falta y todo ese código debería haber sido eliminado porque ya no está en uso. Parece como si el evento bloqueara la recepción, pero ese código es el que viene en la MSDN y yo uso en otros sitios sin problemas, y todo ello se está ejectuando en un background worker independiente de la aplicación... 

    Lo peor de todo es que ese mismo código tampoco funciona en el escritorio... A ver si a alguien se le ocurre algo...


    MVP Visual C++ - Visita mi blog sobre desarrollo: http://geeks.ms/blogs/rfog/

    lunes, 3 de junio de 2013 10:28