簡體   English   中英

UDP客戶端異步不會關閉套接字

[英]UDP client async doesn't close sockets

我正在嘗試編寫自定義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.SocketException”通常只允許使用每個套接字地址(協議/網絡地址/端口)的一種。

我試圖關閉每個端口,但是程序在此行中返回以下異常“ System.ObjectDisposedException”:

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

任何幫助將不勝感激。

注意:經過更多嘗試,我意識到我只有一個例外:“在以前的掃描中未收到任何數據的UDP端口上,通常只允許使用每個套接字地址(協議/網絡地址/端口)。

你有沒有嘗試過:

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
}

然后讓讓客戶端的家伙處理套接字

如果不;

做一個

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

解決 經過更多的研究和艱苦的工作,這是工作結果。 我使用了同步讀取,使用超時來丟棄未接收數據的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的關注。

出現原始問題的原因是因為您應該重新使用對象,而不是一直創建一個新對象。 否則,您將收到消息“每個套接字地址僅一種用法”。UdpClient u = new UdpClient(e);

除非您的主線程在threading.thread.sleep(8)的那8毫秒內有更重要的事情要做,否則我什至不會為async ..所困擾,只需使用.receive()來等待/從套接字緩沖區中讀取。 並像上面最后一樣設置超時時間。 btw thread.sleep的最小長度為8ms到16ms。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM