Frage

Grüße, ich versuche einen Weg zu finden, einen Socket von einer bestimmten IP/Port-Kombination zu „entbinden“.Mein Pseudocode sieht so aus:

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 informiert mich .Net darüber, dass ich bereits einen Socket habe, der an 127.0.0.1:4567 gebunden ist, was technisch gesehen stimmt.Aber egal, welchen Code ich in den Destruktor von ClassA einfüge oder welche Funktionen ich für den Socket aufrufe (ich habe .Close() und .Disconnect(true) ausprobiert), der Socket bleibt stolz an 127.0.0.1:4567 gebunden.Was muss ich tun, um den Socket „entbinden“ zu können?


BEARBEITEN:Ich verlasse mich nicht ausschließlich auf die Speicherbereinigung (obwohl ich diesen Ansatz auch ausprobiert habe).Ich habe versucht, a.Close() oder a.Disconnect() aufzurufen und erst dann aa;das löst das Problem nicht.


BEARBEITEN:Ich habe auch versucht, IDisposable zu implementieren, aber der Code kam nie dorthin, ohne dass ich die Methode aufgerufen habe (was den früheren Versuchen entsprach, da die Methode einfach .Close und .Disconnect ausprobierte).Lassen Sie mich versuchen, .Dispose direkt anzurufen und mich bei Ihnen zu melden.


EDIT (viele Änderungen, Entschuldigung):Das Implementieren von IDisposable und das Aufrufen von a.Dispose(), von wo aus „a“ den Gültigkeitsbereich verliert, funktioniert nicht – meine Dispose-Implementierung muss immer noch entweder .Close oder .Disconnect(true) (oder .Shutdown(Both)) aufrufen, aber keines davon löst die Bindung die Steckdose.

Jede Hilfe wäre dankbar!

War es hilfreich?

Lösung

(Das ist es, was bei mir endlich alles zum Laufen gebracht hat)

Stellen Sie sicher, dass JEDE Steckdose, mit der die Steckdose in A verbunden ist, über einen Anschluss verfügt

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

wird bei der Initiierung festgelegt.

Andere Tipps

Sie können sich nicht darauf verlassen, dass ein Objekt in C# durch Müll gesammelt wird (ich gehe davon aus, dass Sie C# verwenden, basierend auf Tagging), wenn es Ressourcen enthält, z. B. wie in Ihrem Beispiel an die Netzwerkressource gebunden ist oder eine andere Art von Stream enthält, a Dateistream wäre ein häufiges Beispiel.

Sie müssen sicherstellen, dass die Ressourcen, die das Objekt enthält, freigegeben werden, damit es durch den Müll gesammelt werden kann.andernfalls wird es nicht im Müll gesammelt, sondern bleibt irgendwo im Gedächtnis lebendig.Ihr Pseudocode-Beispiel gibt nicht an, dass Sie die Ressourcen freigeben, Sie geben lediglich an, dass das Objekt Müll gesammelt wird (sollte).

Der Garbage Collector garantiert Ihnen nicht, dass der Socket jemals geschlossen wird.Ein vollständiges Beispiel finden Sie hier MSDN-Beispiel.

Es geht vor allem darum, tatsächlich anzurufen Socket.Close() so schnell wie möglich.Beispielsweise könnte ClassA implementieren IEinwegartikel und benutze es so:

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

Der Garbage Collector führt zu einem unbestimmten Zeitpunkt den Finalizer des Objekts aus.Sie könnten die IDisposable-Schnittstelle implementieren und die Dispose()-Methode aufrufen, bevor das Objekt den Gültigkeitsbereich verliert – oder die using-Anweisung das für Sie erledigen lassen.

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

bearbeiten: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())
            {
            }
        }
    }
}

Die beste Lösung besteht darin, einige Male (2-3) erneut zu versuchen, den Socket zu binden.Wenn es beim ersten Versuch fehlschlägt, habe ich festgestellt, dass der ursprüngliche Socket ordnungsgemäß (und dauerhaft) geschlossen wird.

HTH,

_NT

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top