2008-09-07 4 views
4

인사말, 특정 IP/포트 조합에서 소켓을 '바인딩 해제'하는 방법을 찾으려고합니다. 내 의사 코드는 다음과 같습니다 :이 시점에서소켓을 기존 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. 

은, 닷넷 내가 이미 기술적으로 사실이다 127.0.0.1:4567에 바인딩 소켓을 가지고 저를 알려줍니다. 그러나 ClassA의 소멸자에 어떤 코드를 넣든 상관없이 또는 소켓에서 호출 한 함수 (아무리 .Close() 및 .Disconnect (true)를 시도해도) 소켓은 자랑스럽게 127.0.0.1:4567에 바인딩됩니다. 소켓을 un-bind 할 수 있으려면 어떻게해야합니까?


EDIT : 전 가비지 수집에만 의존하지 않습니다. 나는 a.Close() 또는 a.Disconnect()를 호출하고 Aa를 인스턴스화했다. 이것은 문제를 해결하지 못합니다.


편집 : 나는 또한으로 IDisposable을 구현하려했지만, 코드 내가 (이 방법은 단순히 .Close 및 .Disconnect을 시도하는 것처럼 이전 시도의 상당했다) 메소드를 호출하지 않고 거기에 도착하지 않았다. 나에게 직접 전화 해보고 다시 연락하자.


EDIT (편집 많은, 사과) '는이'범위를 잃는 곳에서 구현으로 IDisposable 및 호출 a.Dispose()이 작동하지 않습니다 - 내 폐기 구현이 여전히 .Close 또는 .Disconnect 중 하나를 호출 할 수있다 (true) (또는 .Shutdown (Both))하지만 소켓의 바인딩을 해제하지 않습니다.

도움이 될 것입니다.

답변

3

을 위해 잘 작동하는 A의 소켓 연결 대상은

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

se t 시작됩니다.

+0

실제로 이전 소켓이 여전히 포트에 바인딩되어 있음을 의미하지는 않습니까? http://msdn.microsoft.com/en-us/library/cc319473.aspx ReuseAddress 이미 사용중인 주소에 바인딩을 허용하는 데 사용하는 값입니다. * * 사용중 *이 아니 * * – VolkerK

+0

VolkerK; 내 생각 엔 당신이 맞다. 여기서주의해야하며 이전 인스턴스가 실제로 사라 졌는지 확인해야합니다. 기본적으로 버클리 소켓은 포트/소켓 조합을 해제하기 전에 5 분 동안 대기합니다. 이것이 내가 작동하는 유일한 해결 방법입니다. – AlexeyMK

0

예를 들어 네트워크 리소스에 바인딩 된 리소스를 보유하고 있거나 다른 종류의 리소스를 보유하고있는 경우 C#에서 가비지 수집 대상 개체에 의존 할 수 없습니다 (태깅을 기반으로 C#을 사용한다고 가정합니다) 스트림의 경우 파일 스트림이 일반적인 예입니다.

가비지 수집 할 수 있도록 개체가 보유하고있는 리소스를 릴리스해야합니다. 그렇지 않으면 가비지 수집되지 않지만 메모리의 어딘가에 남아 있습니다. 귀하의 의사 코드 예제에서는 리소스를 해제하고 있다는 것을 알려주지 않습니다. 객체가 가비지 수집을 가져오고 (가져와야한다고) 명시해야합니다.

0

가비지 수집기가 소켓을 항상 닫을 것이라고 보장하지 않습니다. 전체 예제를 보려면 MSDN example을 읽으십시오.

요점은 실제로 Socket.Close()을 가능한 빨리 호출하는 것입니다. 예를 들어,를 ClassA는 IDisposable을 구현할 수와 같이 사용 :

using (ClassA a = new ClassA()) 
{ 
    // code goes here 
} 
// 'a' is now disposed and the socket is closed 
0

가비지 컬렉터는 불확정시 개체의 종료자를 실행합니다. 개체가 범위를 잃기 전에 IDisposable 인터페이스를 구현하고 Dispose() 메서드를 호출 할 수 있습니다. 또는 using 문을 사용하여 처리 할 수 ​​있습니다.

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

편집을 참조하십시오

확실 매주 소켓을 확인 (이 마침내 나를 위해 작동하는 모든 것을 가지고 무엇을) 나

 
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()) 
      { 
      } 
     } 
    } 
} 
+0

IPAddress.Any 작업이 허용됩니다 뭐죠 그것의 수 (그 다른 IP 주소마다 사용)

_NT. 어쨌든이 방법으로는 문제가 해결되지 않습니다 (불분명 함). ClassA는 네트워크 통신 관리자 클래스이고 Socket은 클래스 전체 변수입니다. – AlexeyMK

0

최상의 해결 방법은 소켓을 몇 번 묶어 다시 시도하는 것입니다 (2-3). 첫 번째 시도에서 실패하면 원래 소켓을 제대로 (영구적으로) 닫을 것입니다.

HTH,

관련 문제