Question

Salutations, j'essaie de trouver un moyen de « dissocier » un socket d'une combinaison IP/Port particulière.Mon pseudocode ressemble à ceci :

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.

À ce stade, .Net m'informe que j'ai déjà un socket lié à 127.0.0.1:4567, ce qui est techniquement vrai.Mais quel que soit le code que je mets dans le destructeur de ClassA, ou quelles que soient les fonctions que j'appelle sur le socket (j'ai essayé .Close() et .Disconnect(true)), le socket reste fièrement lié à 127.0.0.1:4567.Que dois-je faire pour pouvoir « dissocier » le socket ?


MODIFIER:Je ne compte pas uniquement sur le garbage collection (même si j'ai également essayé cette approche).J'ai essayé d'appeler a.Close() ou a.Disconnect() et ensuite seulement d'instancier aa;cela ne résout pas le problème.


MODIFIER:J'ai également essayé d'implémenter IDisposable, mais le code n'est jamais arrivé sans que j'appelle la méthode (ce qui était l'équivalent des tentatives précédentes, car la méthode essayait simplement .Close et .Disconnect).Laissez-moi essayer d'appeler directement .Dispose et je vous répondrai.


EDIT (beaucoup de modifications, excuses) :Implémenter IDisposable et appeler a.Dispose() d'où 'a' perd la portée ne fonctionne pas - mon implémentation de Dispose doit toujours appeler .Close ou .Disconnect(true) (ou .Shutdown(Both)) mais aucun de ceux-ci ne se dissocie la prise.

Toute aide serait appréciée!

Était-ce utile?

La solution

(c'est ce qui a finalement fait que tout fonctionne pour moi)

Assurez-vous que CHAQUE prise à laquelle la prise en A se connecte a

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

fixé dès son initiation.

Autres conseils

vous ne pouvez pas compter sur un objet récupéré en C# (je suppose que vous utilisez C#, basé sur le balisage) s'il contient des ressources, comme être lié à la ressource réseau comme dans votre exemple, ou contenir un autre type de flux, un le flux de fichiers serait un exemple courant.

vous devez vous assurer de libérer les ressources que contient l'objet, afin qu'il puisse être récupéré.sinon, il ne sera pas récupéré, mais restera vivant quelque part dans la mémoire.votre exemple de pseudocode ne fournit pas que vous libérez les ressources, vous indiquez simplement que l'objet est (devrait) être récupéré.

Le garbage collector ne vous garantit pas que le socket sera un jour fermé.Pour un exemple complet, lisez ceci Exemple MSDN.

L'essentiel est d'appeler réellement Socket.Close() dès que possible.Par exemple, ClassA pourrait implémenter IJetable et utilisez-le comme ceci :

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

Le garbage collector exécute le finaliseur de l'objet à un moment indéterminé.Vous pouvez implémenter l'interface IDisposable et appeler la méthode Dispose() avant que l'objet ne perde la portée - ou laisser l'instruction using le faire pour vous.

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

modifier:fonctionne bien pour moi

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

La meilleure solution est de réessayer de lier le socket plusieurs fois (2-3).Lors de la première tentative, en cas d'échec, j'ai constaté qu'il fermerait correctement (et définitivement) le socket d'origine.

HTH,

_NT

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top