2008-09-07 5 views
4

Liebe Grüße, ich versuche eine Möglichkeit zu finden, einen Socket von einer bestimmten IP/Port-Kombination zu "lösen". Mein Pseudo-Code sieht wie folgt aus:Ich kann einen Socket nicht an eine vorhandene IP/Port-Kombination binden

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. 

An diesem Punkt .Net mich darüber informiert, dass ich bereits einen Sockel bekam zu 127.0.0.1:4567 gebunden, die technisch wahr ist. Aber egal welchen Code ich in den Destruktor von ClassA lege oder egal, welche Funktionen ich beim Socket anrufe (ich habe .Close() und .Disconnect (true) versucht), der Socket bleibt stolz an 127.0.0.1:4567 gebunden. Was kann ich tun, um den Socket zu entbinden?

EDIT: Ich bin nicht allein auf Garbage Collection angewiesen Ich habe versucht, a.Close() oder a.Disconnect() aufzurufen und erst dann aa; Das löst das Problem nicht.


EDIT: Ich habe versucht, auch IDisposable Umsetzung, aber der Code bekam nie ohne mein Aufruf der Methode (das entspricht früheren Versuchen war das Verfahren, wie einfach .Close und .Disconnect versuchen würde). Lassen Sie mich versuchen. Rufen Sie direkt an und melden Sie sich an.


EDIT (viele Änderungen, Entschuldigungen): Implementieren von IDisposable und ruft a.Dispose(), von wo ‚a‘ Umfang verliert funktioniert nicht - meine Entsorgen Umsetzung noch nennen entweder .Close oder .Disconnect hat (true) (oder .Shutdown (Both)), aber keiner davon löst den Socket.

Jede Hilfe wäre willkommen!

Antwort

3

(das ist, was schließlich alles bekam für mich zu arbeiten)

Stellen Sie sicher, jeder Steckdose, dass die Steckdose in A verbindet mit hat

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

se t nach der Initiierung.

+0

Heißt das nicht, dass der vorherige Socket immer noch da ist und an den Port gebunden ist? http://msdn.microsoft.com/en-us/library/cc319473.aspx ReuseAddress Ein Wert, den Sie verwenden, um die Bindung an eine Adresse zuzulassen, die bereits verwendet wird. * ist * in Benutzung, nicht * wurde * – VolkerK

+0

Volkerk; Ich denke, du hast recht. Hier müssen Sie vorsichtig sein und sicherstellen, dass die vorherige Instanz wirklich verschwunden ist. Berkley-Sockets warten standardmäßig 5 Minuten, bevor sie eine Port/Socket-Kombination freigeben. Dies ist die einzige Problemumgehung, die ich gefunden habe. – AlexeyMK

0

Sie können sich nicht darauf verlassen, dass das Objekt in C# gesammelt wird (ich nehme an, Sie verwenden C# basierend auf dem Tagging), wenn es Ressourcen enthält, wie in Ihrem Beispiel an die Netzwerkressource gebunden zu sein von Stream wäre ein Dateistream ein häufiges Beispiel.

müssen Sie sicherstellen, dass die Ressourcen freigegeben werden, die das Objekt enthält, so dass es Müll gesammelt werden kann. sonst wird es nicht Müll gesammelt, sondern irgendwo in der Erinnerung bleiben. In Ihrem Pseudocode-Beispiel ist nicht vorgesehen, dass Sie die Ressourcen freigeben. Sie geben lediglich an, dass das Objekt Garbage-Collections erhält (sollte).

0

Der Garbage Collector garantiert Ihnen nicht, dass der Socket jemals geschlossen wird. Für ein vollständiges Beispiel lesen Sie diese MSDN example.

Der wichtigste Punkt ist, so schnell wie möglich zu rufen Socket.Close(). Zum Beispiel könnte KlasseA IDisposable implementieren und es wie folgt verwendet werden:

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

Der Garbage Collector läuft die Finalizer des Objekts an einem gewissen unbestimmte Zeit. Sie können die IDisposable-Schnittstelle implementieren und die Dispose() -Methode aufrufen, bevor das Objekt den Gültigkeitsbereich verliert - oder die using-Anweisung für Sie ausführen lassen.

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

edit: funktioniert gut für mich

 
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

Es ist möglich, dass IPAddress.Any ist was diese (sein mit unterschiedlichen IP-Adressen jedes Mal) zu arbeiten, ermöglicht. In jedem Fall würde dies das Problem nicht lösen (tut mir leid, dass es unklar ist): ClassA ist eine Netzwerkkommunikationsmanagerklasse und der Socket ist eine klassenweite Variable. – AlexeyMK

0

Die beste Lösung besteht darin, den Sockel einige Male zu binden (2-3). Auf den ersten Versuch, wenn es fehlschlägt, habe ich festgestellt, dass es den ursprünglichen Socket richtig (und dauerhaft) schließt.

HTH,

_NT

Verwandte Themen