C# (显然)优雅地关闭UDPClient会使套接字阻塞

C# (显然)优雅地关闭UDPClient会使套接字阻塞,c#,.net,multithreading,sockets,udpclient,C#,.net,Multithreading,Sockets,Udpclient,尽管下面的代码显然关闭了UDP套接字,但它仍然挂起,无法重新连接到相同的地址/端口 以下是我使用的类变量: Thread t_listener; List<string> XSensAvailablePorts; private volatile bool stopT_listener = false; volatile UdpClient listener; IPEndPoint groupEP; 方法如下(我在Receiv

尽管下面的代码显然关闭了UDP套接字,但它仍然挂起,无法重新连接到相同的地址/端口

以下是我使用的类变量:

    Thread t_listener;
    List<string> XSensAvailablePorts;
    private volatile bool stopT_listener = false;        
    volatile UdpClient listener;
    IPEndPoint groupEP;
方法如下(我在
Receive
上使用一个超时,以便在套接字上没有发送任何内容并且发出
Stop
时不使其被阻止):


尽管在debug中检查套接字是否已关闭,但如果我尝试连接到同一端口,我无法这样做,因为它会引发
SocketException
,表示通常只允许使用一个端口/地址。

我将您提供的代码以简单的形式放入运行它的程序中,然后。。。我不能直接重现你的问题。虽然我没有向客户端发送任何数据,但据我所知,它不应该改变任何东西,因为它是UDP,我们正在调查(重新)打开套接字,而不是传输数据

单击开始/停止按钮时,插座始终正确打开和关闭,重新打开可按预期工作。 对我来说,强制执行您提到的SocketException的唯一方法是引入一些明显的套接字逻辑误用:

  • 运行应用程序的两个实例,并在两个实例中单击“开始”
  • 删除关机和关闭两种情况(停止不关闭插座)
  • 运行应用程序,打开套接字,关闭应用程序而不关闭套接字,再次运行应用程序,尝试打开套接字
  • 我在代码中所做的唯一更改是删除ParseData(…)行,并将一些端口添加到XSensAvailableReports列表中


    你能检查一下端口在你关闭后是否仍然打开吗?您可以使用
    netstat-an
    ,或优秀的ProcessExplorer工具。您还可以检查t_侦听器线程是否正确终止(标准任务管理器或ProcessExplorer可以帮助您)。

    将侦听器对象设置为NULL,以便释放资源,这也会释放连接。

    我也有同样的问题,问题出在UDPClient.Receive(),她使插座处于已使用状态,即使您呼叫Close/shutdown/`

    try{ // receive loop}
    catch{}
     finally {
    UDP_Listner.Close();
                        UDP_Listner = null;
                    }
    
    编辑:

    t_listener = new Thread(UDPListener);//replace by :
     t_listener = new Thread(new ThreadStart(UDPListener));
    
    `


    为了安全地关闭socket和thread()

    我也有同样的问题,我是最安全的程序员,我总是很好地关闭所有东西。但是我发现.net类关闭套接字的速度不够快。因为如果我走得慢,它不会发生,但如果我打开和关闭(完全清理)并快速打开它,我会得到同样的错误。尤其是当用户希望再次运行相同的代码并再次打开端口时。

    可能是一个旧答案,但在您试图找到一个可用的端口时,失败了,我会在下一次迭代之前处理您测试的侦听器实例

                try
                {
                    currPort = Int32.Parse(XSensAvailablePorts[currAttempt]);
                    listener = new UdpClient(currPort);
                    successfullAttempt = true;
                }
                catch (Exception e)
                {
                    currAttempt++;
    
                    if(listener != null)
                    {
                       listener.Close();
                    }
                }
    

    我认为绑定或重用可以解决这个问题(即使套接字还没有关闭,它也可以重用,并且不会抛出错误) 示例代码:

    udpClient = new UdpClient();
    udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
    udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, p));
    

    当您单击按钮时,可能是什么
    listener.Client
    null
    ?您将不会调用
    listener.Close()
    。@Sinatr我签入了debug,但事实并非如此。Close()应该完全处理该对象。这一定是其他原因,比如没有正确地关闭套接字(可能是由于没有处理某些异常,只是跳过了这些异常)。我不知道,因为我刚刚使用了.BeginReceive异步方法来处理数据;pI无法访问我与之通信的硬件/软件(正如您可能从我访问XSens body suit用于身体跟踪的套接字流的变量名称中了解到的),但我将在下周进行检查。我对这个组件的数据流有太多问题,我怀疑这可能是服务器的错误,有些东西出了问题。我没有将对象设置为null并等待GC释放资源,而是使用Close()/Dispose()强制释放资源,但也没有起作用。这是回答还是评论?
    t_listener = new Thread(UDPListener);//replace by :
     t_listener = new Thread(new ThreadStart(UDPListener));
    
                try
                {
                    currPort = Int32.Parse(XSensAvailablePorts[currAttempt]);
                    listener = new UdpClient(currPort);
                    successfullAttempt = true;
                }
                catch (Exception e)
                {
                    currAttempt++;
    
                    if(listener != null)
                    {
                       listener.Close();
                    }
                }
    
    udpClient = new UdpClient();
    udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
    udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, p));