4

问候,我正在尝试找到一种方法来从特定的 IP/端口组合中“解除绑定”套接字。我的伪代码如下所示:

ClassA a = new ClassA(); //(class A  instantiates socket and binds it to 127.0.0.1:4567) 
//do something 
//...much later, a has been garbage-collected away.
ClassA aa = new ClassA(); //crash here.

此时,.Net 通知我已经有一个绑定到 127.0.0.1:4567 的套接字,这在技术上是正确的。但是无论我在 ClassA 的析构函数中放入什么代码,或者无论我在套接字上调用什么函数(我尝试过 .Close() 和 .Disconnect(true)),套接字仍然自豪地绑定到 127.0.0.1:4567。我该怎么做才能“取消绑定”套接字?


编辑:我不仅仅依赖垃圾收集(尽管我也尝试过这种方法)。我尝试调用 a.Close() 或 a.Disconnect() ,然后才实例化 aa; 这并不能解决问题。


编辑:我也尝试过实现 IDisposable,但是如果没有我调用该方法,代码就永远不会到达那里(这相当于早期的尝试,因为该方法只会尝试 .Close 和 .Disconnect)。让我尝试直接调用 .Dispose 并回复您。


编辑(大量编辑,道歉):实现 IDisposable 并从“a”失去范围的地方调用 a.Dispose() 不起作用 - 我的 Dispose 实现仍然必须调用 .Close 或 .Disconnect(true) (或 .Shutdown (两者))但没有一个解除套接字绑定。

任何帮助,将不胜感激!

4

5 回答 5

3

(这就是最终让一切都为我工作的原因)

确保 A 中的套接字连接到的每个套接字都有

socket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReuseAddress, true);

在启动时设置。

于 2008-09-07T12:34:48.550 回答
0

你不能依赖在 C# 中被垃圾收集的对象(我假设你正在使用 c#,基于标记)如果它拥有像你的示例中那样绑定到网络资源的资源,或者拥有某种其他类型的流,a文件流将是一个常见的例子。

您必须确保释放对象所持有的资源,以便对其进行垃圾收集。否则它不会被垃圾收集,而是留在内存中的某个地方。您的伪代码示例没有提供您正在释放资源,您只是声明该对象得到(应该得到)垃圾收集。

于 2008-09-07T12:02:41.153 回答
0

垃圾收集器不保证套接字将永远关闭。有关完整示例,请阅读此MSDN 示例

要点是尽快实际调用Socket.Close()。例如,ClassA 可以实现IDisposable并像这样使用它:

using (ClassA a = new ClassA()) 
{
    // code goes here
}
// 'a' is now disposed and the socket is closed
于 2008-09-07T12:02:48.253 回答
0

垃圾收集器在某个不确定的时间运行对象的终结器。您可以实现 IDisposable 接口并在对象失去 Scope 之前调用 Dispose() 方法 - 或者让 using 语句为您执行此操作。

请参阅http://msdn.microsoft.com/en-us/library/system.idisposable.aspxhttp://msdn.microsoft.com/en-us/library/yh598w02.aspx

编辑:对我来说很好

使用系统;
使用 System.Net.Sockets;
使用 System.Net;

命名空间 ConsoleApplication1
{
    课堂节目
    {
        类 ClassA : IDisposable
        {
            受保护的 Socket ;
            公共类A()
            {
                s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                s.Bind(new IPEndPoint(IPAddress.Any, 5678));
            }

            公共无效处置()
            {
                s.关闭();
            }
        }

        静态无效主要(字符串 [] 参数)
        {
            使用(ClassA a=new ClassA()) {
            }
            使用 (ClassA b = new ClassA())
            {
            }
        }
    }
}
于 2008-09-07T12:08:29.643 回答
0

最好的解决方案是重试几次绑定套接字(2-3)。在第一次尝试时,如果它失败了,我发现它会正确(并且永久地)关闭原始套接字。

高温下,

_NT

于 2009-09-30T10:47:42.190 回答