简体   繁体   中英

UDP client async doesn't close sockets

I'm trying to program a custom UDP port sniffer. I'm trying to scan the local network looking for the UDP ports that are receiving data.Maybe this is a really trivial question, but I'm stuck here. I have tried a lot of examples and tutorials but I can't find a good solution. I have done this succesfully, using these two methods:

    private static int udpListenPort = 1026;
bool flag=false;
public void ReceiveMessages()
{
    for (udpListenPort = 1026;  udpListenPort< 1200; udpListenPort++)
    {
        if (flag)
        {
            messageReceived = false;
            IPEndPoint e = new IPEndPoint(IPAddress.Any, udpListenPort);
            UdpClient u = new UdpClient(e);
            UdpState s = new UdpState();
            s.e = e;
            s.u = u;

            u.BeginReceive(new AsyncCallback(CheckUdpPort), s);
            for (int i = 0; i < 5; i++)
            {
                Thread.Sleep(8);
                if (messageReceived)
                {
                    break;
                }
            }
            if (messageReceived)
            {
                // Updating UI
            }
            //u.Close();    // I'm trying this but returns an exception
            e = null;
            u = null;
            s = null;

        }
    }
}

And this:

    public class UdpState
{
    public IPEndPoint e;
    public UdpClient u;
}
private static void CheckUdpPort(IAsyncResult ar)
{
    UdpClient u = (UdpClient)((UdpState)(ar.AsyncState)).u;
    IPEndPoint e = (IPEndPoint)((UdpState)(ar.AsyncState)).e;

    Byte[] data = u.EndReceive(ar, ref e);

    // Some code to filter the data received

    messageReceived = true;

}

I'm using these methods in a WPF program. When the scan finalize and I try to start it again, the IDE retunrs the following exception in this point:

IPEndPoint e = new IPEndPoint(IPAddress.Any, udpListenPort);
            UdpClient u = new UdpClient(e);  //HERE
            UdpState s = new UdpState();

System.Net.Sockets.SocketException "Only one usage of each socket address (protocol/network address/port) is normally permitted."

I have tried to close each port, but the program returns the following exception "System.ObjectDisposedException" in this line:

Byte[] data = u.EndReceive(ar, ref e);

Any help will be very much appretiated.

Note: After more attempts, I realized that I only have the exception "Only one usage of each socket address (protocol/network address/port) is normally permitted. on the UDP ports that haven't received any data in the previous scan.

Have you tried:

u.Client.Shutdown();
u.Client.Close();

instead of the:

u.Close();

Following the msdn:

http://msdn.microsoft.com/en-us/library/wahsac9k.aspx

"For connection-oriented protocols, it is recommended that you call Shutdown before calling the Close method. This ensures that all data is sent and received on the connected socket before it is closed."

As you're working directly on the sockets, kinda.

UdpClient even implements IDisposable

public class UdpClient : IDisposable

Meaning you may use it in a

using(u = new UdpClient(foo)){
//do some stuff
}

Then you let the guys who made the client dispose of the sockets

if not;

do a

try{
//do stuff
}
finally{
u.client.shudown();
u.client.close();
}

SOLVED . After more research and rough work, here is the working result. I have used synchronous reading, using the timeout to discard the UDP ports that are not receiving data.

private void BETAScanNetwork()
{
    int contador = 0;
    for (int i = 1140; i <= 1160; i++)
    {
        UdpClient listener = null;
        bool incoming = false;
        try
        {
            listener = new UdpClient(i);
            var groupEp = new IPEndPoint(IPAddress.Any, i);

            listener.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 50);
            byte[] data = listener.Receive(ref groupEp);
            incoming = true;
            listener.Client.Shutdown(SocketShutdown.Both);
            listener.Client.Close();
            // Managing received data
        }
        catch (System.Net.Sockets.SocketException e)
        {
            var excp = e.SocketErrorCode;
            if (excp== SocketError.TimedOut)
            {
                continue;   
            }
            else
            {
                throw;
            }
        }
        finally
        {
            if (listener != null && !incoming)
            {
                listener.Client.Shutdown(SocketShutdown.Receive);
                listener.Close();
            }
        }
    }
}

Thanks for the interest shown, @lord_alek1.

the reason you had the original problem is because you should have re-used your object instead of creating a new one all the time. otherwise you will get the message "Only one usage of each socket address" UdpClient u = new UdpClient(e);

unless your main thread has something more important to do during those 8milliseconds that you threading.thread.sleep(8), I would not even bother with async.. just use .receive() to wait/read from the socket buffer. and set the timeout as you did above in the end. btw thread.sleep can be anywhere from 8ms to 16ms minimum.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM