Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Can';t将套接字重新绑定到现有IP/端口组合_C#_.net_Networking_Sockets - Fatal编程技术网

C# Can';t将套接字重新绑定到现有IP/端口组合

C# Can';t将套接字重新绑定到现有IP/端口组合,c#,.net,networking,sockets,C#,.net,Networking,Sockets,您好,我正在设法从特定的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. using (Cla

您好,我正在设法从特定的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.
using (ClassA a = new ClassA()) 
{
    // code goes here
}
// 'a' is now disposed and the socket is closed
此时,.Net通知我已经有一个绑定到127.0.0.1:4567的套接字,这在技术上是正确的。但是,无论我在ClassA的析构函数中放入了什么代码,也不管我在套接字上调用了什么函数(我已经尝试了.Close()和.Disconnect(true)),套接字仍然自豪地绑定到127.0.0.1:4567。如何才能“解除绑定”套接字


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


编辑:我也尝试过实现IDisposable,但如果我不调用该方法,代码就永远无法实现(这与以前的尝试相当,因为该方法只需尝试.Close和.Disconnect)。让我试着打电话给你。直接处理,然后再打给你


编辑(大量编辑,抱歉):实现IDisposable并从“a”失去作用域的位置调用.Dispose(),这不起作用-我的Dispose实现仍然必须调用.Close或.Disconnect(true)(或.Shutdown(两者)),但这些都不能解除套接字的绑定


任何帮助都将不胜感激

您不能依赖对象在C#中被垃圾收集(我假设您使用的是C#,基于标记),如果它包含资源,如绑定到网络资源,如您的示例中所示,或包含其他类型的流,则文件流将是一个常见的示例


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

垃圾回收器不保证套接字将永远关闭。有关完整的示例,请阅读以下内容

主要的一点是尽快实际调用
Socket.Close()
。例如,ClassA可以这样实现和使用它:

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.
using (ClassA a = new ClassA()) 
{
    // code goes here
}
// 'a' is now disposed and the socket is closed

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

看到和

编辑:对我来说很好

using System; using System.Net.Sockets; using System.Net; namespace ConsoleApplication1 { class Program { class ClassA : IDisposable { protected Socket s; public ClassA() { s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); s.Bind(new IPEndPoint(IPAddress.Any, 5678)); } public void Dispose() { s.Close(); } } static void Main(string[] args) { using(ClassA a=new ClassA()) { } using (ClassA b = new ClassA()) { } } } } 使用制度; 使用System.Net.Sockets; Net系统; 命名空间控制台应用程序1 { 班级计划 { 类别A:IDisposable { 受保护插座; 公共甲级() { s=新套接字(AddressFamily.InterNetwork、SocketType.Stream、ProtocolType.Tcp); s、 绑定(新的IPEndPoint(IPAddress.Any,5678)); } 公共空间处置() { s、 Close(); } } 静态void Main(字符串[]参数) { 使用(ClassA=新ClassA()){ } 使用(ClassA b=new ClassA()) { } } } } (这就是最终让一切为我工作的原因)

确保中的插座连接到的每个插座都具有

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

一开始就开始

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

嗯,


_NT

这难道不意味着事实上,前一个套接字仍然存在并绑定到端口吗?ReuseAddress一个值,用于允许绑定到已在使用的地址。正在使用中,而不是beenVolkerK;我想你是对的。这是你必须小心的地方,确保前一个实例真的消失了;默认情况下,Berkley套接字将在释放端口/套接字组合之前等待5分钟;这是我发现的唯一可行的解决方法。可能是IPAddress。任何允许它工作的东西(每次都使用不同的IP地址)。无论如何,这都不能解决问题(很抱歉不清楚):ClassA是一个网络通信管理器类,Socket是一个类范围的变量。