UDP客户端async没有关闭套接字

本文关键字:套接字 客户端 async UDP | 更新日期: 2023-09-27 18:09:58

我正在尝试编程一个自定义UDP端口嗅探器。我试图扫描本地网络寻找正在接收数据的UDP端口。也许这是一个微不足道的问题,但我被困在这里了。我已经尝试了很多例子和教程,但我找不到一个好的解决方案。我使用这两种方法成功地做到了这一点:

    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;
        }
    }
}

:

    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;
}

我在WPF程序中使用这些方法。当扫描完成并且我尝试再次启动它时,IDE在这一点上返回以下异常:

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

System.Net.Sockets。每个套接字地址(协议/网络地址/端口)通常只允许使用一次。

我已经尝试关闭每个端口,但是程序返回以下异常"System。"ObjectDisposedException"

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

任何帮助都将非常感激。

注意:经过更多的尝试,我意识到我只有例外"每个套接字地址(协议/网络地址/端口)通常只允许使用一次。

UDP客户端async没有关闭套接字

SOLVED。经过更多的研究和粗略的工作,这是工作结果。我已经使用同步读取,使用超时丢弃未接收数据的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();
            }
        }
    }
}

感谢您的关注,@lord_alek1.

你试过了吗:

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

代替:

u.Close();

msdn后面:

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

"对于面向连接的协议,建议在调用Close方法之前调用Shutdown。这确保了在连接的套接字关闭之前,所有数据都在套接字上发送和接收。"

当你直接在套接字上工作时,有点。

UdpClient甚至实现了IDisposable

public class UdpClient : IDisposable

意思是你可以在

中使用它
using(u = new UdpClient(foo)){
//do some stuff
}

然后让客户端处理socket

如果没有;

做一个

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

出现原始问题的原因是您应该重用您的对象,而不是一直创建一个新对象。否则,您将得到消息"每个套接字地址只使用一次"。UdpClient u = new UdpClient(e);

除非你的主线程在你threading.thread.sleep(8)的8毫秒内有更重要的事情要做,否则我甚至不会打扰异步。只需使用.receive()从套接字缓冲区等待/读取。最后像上面那样设置超时。顺便说一句线程。睡眠时间最少为8ms到16ms。