web-dev-qa-db-ja.com

ソケットでのリスニングを停止する適切な方法

ソケットで接続をリッスンするサーバーがあります。

public class Server
{
    private Socket _serverSocket;

    public Server()
    {
        _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        _serverSocket.Bind(new IPEndPoint(IPAddress.Any, 1234));
        _serverSocket.Listen(1);
    }

    public void Start()
    {
        _serverSocket.BeginAccept(HandleAsyncConnectionMethod, null);
    }

    public void Stop()
    {
        //????? MAGIC ?????
    }

    //... rest of code here
}

ソケットを閉じる正しい(クリーンな)方法は何ですか?

電話するだけで十分ですか?

_serverSocket.Disconnect(true);

stop()メソッドで?または、接続をきれいに閉じるために発生する必要がある他の作業はありますか?

21
Anton

TCP接続の終了には、4方向のハンドシェイクが正しく含まれます。両端がシャットダウンしていることを相手に通知してから、互いのシャットダウンを確認する必要があります。

ウィキペディアはプロセスを説明しています: http://en.wikipedia.org/wiki/Transmission_Control_Protocol#Connection_termination

この投稿では、C#でそれを実現する方法について説明しています: http://vadmyst.blogspot.com/2008/04/proper-way-to-close-tcp-socket.html

3
Unprompted

着信TCP接続をリッスンしているので、Stop()メソッドを持つ System.Net.Sockets.TcpListener を使用できます。非同期操作はありません。しかし。

2
Wim Coenen

例外なく正しく閉じる2つの方法

1)一時的な接続ソケットを作成し、それをリスニングソケットに接続して、ハンドラーをトリガーできるようにします。その後、通常のEndAcceptで終了し、その後両方を閉じます。

2)Close(0)リスニングソケットだけで、コールバックへの誤ったショットが発生します。次にリスニングソケットを調べると、その状態が「クローズ」および「破棄」されていることがわかります。これが、EndAcceptを呼び出すと例外が発生する理由です。それを無視して、EndAcceptを呼び出さないでください。リスニングソケットはタイムアウトなしですぐにダウンします。

Acceptの呼び出しをすぐに中断させる最もクリーンな方法は、_serverSocket.Dispose();を呼び出すことです。 ShutdownやDisconnectなどのメソッドを他に呼び出すと、例外がスローされます。

0