简体   繁体   English

UDP客户端异步不会关闭套接字

[英]UDP client async doesn't close sockets

I'm trying to program a custom UDP port sniffer. 我正在尝试编写自定义UDP端口嗅探器。 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. 我正在尝试扫描本地网络以查找正在接收数据的UDP端口。也许这是一个非常琐碎的问题,但我被困在这里。 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. 我在WPF程序中使用这些方法。 When the scan finalize and I try to start it again, the IDE retunrs the following exception in this point: 扫描完成后,我尝试再次启动它,此时IDE重新调整以下异常:

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." “ System.Net.Sockets.SocketException”通常只允许使用每个套接字地址(协议/网络地址/端口)的一种。

I have tried to close each port, but the program returns the following exception "System.ObjectDisposedException" in this line: 我试图关闭每个端口,但是程序在此行中返回以下异常“ System.ObjectDisposedException”:

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. 注意:经过更多尝试,我意识到我只有一个例外:“在以前的扫描中未收到任何数据的UDP端口上,通常只允许使用每个套接字地址(协议/网络地址/端口)。

Have you tried: 你有没有尝试过:

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

instead of the: 而不是:

u.Close();

Following the msdn: 跟随msdn:

http://msdn.microsoft.com/en-us/library/wahsac9k.aspx 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." “对于面向连接的协议,建议在调用Close方法之前先调用Shutdown。这可确保在关闭套接字之前,已在连接的套接字上发送和接收所有数据。”

As you're working directly on the sockets, kinda. 当您直接在套接字上工作时,有点。

UdpClient even implements IDisposable UdpClient甚至实现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. 我使用了同步读取,使用超时来丢弃未接收数据的UDP端口。

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. 感谢您对@ 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); 否则,您将收到消息“每个套接字地址仅一种用法”。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. 除非您的主线程在threading.thread.sleep(8)的那8毫秒内有更重要的事情要做,否则我什至不会为async ..所困扰,只需使用.receive()来等待/从套接字缓冲区中读取。 and set the timeout as you did above in the end. 并像上面最后一样设置超时时间。 btw thread.sleep can be anywhere from 8ms to 16ms minimum. btw thread.sleep的最小长度为8ms到16ms。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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