4

こんにちは、特定の 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.

この時点で、.Net は、127.0.0.1:4567 にバインドされたソケットを既に取得していることを通知します。これは技術的には正しいです。しかし、ClassA のデストラクタにどんなコードを入れても、ソケットでどんな関数を呼び出しても (.Close() と .Disconnect(true) を試しました)、ソケットは誇らしげに 127.0.0.1:4567 にバインドされたままです。ソケットを「バインド解除」できるようにするにはどうすればよいですか?


編集:私はガベージコレクションだけに依存しているわけではありません(そのアプローチも試しましたが)。a.Close() または a.Disconnect() を呼び出してから、aa; をインスタンス化しようとしました。これは問題を解決しません。


編集: IDisposable の実装も試みましたが、メソッドを呼び出さずにコードを取得することはできませんでした (メソッドは単純に .Close と .Disconnect を試行するため、以前の試行と同等でした)。.Dispose に直接電話して、折り返しご連絡いたします。


編集 (多くの編集、謝罪): IDisposable を実装し、「a」がスコープを失う場所から a.Dispose() を呼び出すことは機能しません - 私の Dispose 実装は、まだ .Close または .Disconnect(true) (または .Shutdown のいずれかを呼び出す必要があります) (両方))しかし、ソケットのバインドを解除するものはありません。

どんな助けでも大歓迎です!

4

5 に答える 5

3

(これが最終的に私のためにすべてを機能させたものです)

Aのソケットが接続するすべてのソケットにあることを確認してください

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

開始時に設定します。

于 2008-09-07T12:34:48.550 に答える
0

あなたの例のようにネットワークリソースにバインドされているようなリソースを保持している場合、または他の種類のストリームを保持している場合、オブジェクトがC#でガベージコレクションされることに依存することはできません(タグ付けに基づいてC#を使用していると仮定します)ファイル ストリームが一般的な例です。

ガベージ コレクションを実行できるように、オブジェクトが保持しているリソースを確実に解放する必要があります。そうしないと、ガベージ コレクションは行われず、メモリ内のどこかに残ります。あなたの疑似コードの例では、リソースの解放を行っていることを示していません。オブジェクトがガベージコレクションを取得する (取得する必要がある) と述べているだけです。

于 2008-09-07T12:02:41.153 に答える
0

ガベージ コレクターは、ソケットが閉じられることを保証しません。完全な例については、このMSDN の例を参照してください。

重要なポイントは、実際にSocket.Close()できるだけ早く電話することです。たとえば、ClassA はIDisposableを実装し、次のように使用できます。

using (ClassA a = new ClassA()) 
{
    // code goes here
}
// 'a' is now disposed and the socket is closed
于 2008-09-07T12:02:48.253 に答える
0

ガベージ コレクターは、不確定な時間にオブジェクトのファイナライザーを実行します。IDisposable インターフェイスを実装し、オブジェクトが Scope を失う前に Dispose() メソッドを呼び出すか、using ステートメントでそれを行うことができます。

http://msdn.microsoft.com/en-us/library/system.idisposable.aspxおよびhttp://msdn.microsoft.com/en-us/library/yh598w02.aspxを参照してください。

編集:私にとってはうまくいきます

システムを使用する;
System.Net.Sockets の使用;
System.Net を使用。

名前空間 ConsoleApplication1
{
    クラス プログラム
    {
        クラス ClassA : IDisposable
        {
            protected Socket s;
            public ClassA()
            {
                s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                s.Bind(新しい IPEndPoint(IPAddress.Any, 5678));
            }

            public void Dispose()
            {
                s.Close();
            }
        }

        static void Main(string[] args)
        {
            using(ClassA a=new ClassA()) {
            }
            (ClassA b = new ClassA()) を使用
            {
            }
        }
    }
}
于 2008-09-07T12:08:29.643 に答える
0

最善の解決策は、ソケットのバインドを数回 (2 ~ 3 回) 再試行することです。最初の試行で、失敗した場合、元のソケットを適切に (そして永久に) 閉じることがわかりました。

HTH、

_NT

于 2009-09-30T10:47:42.190 に答える