1

私は Ubuntu Linux カーネル 3.5.0-23 で epoll サーバーを作成しましたが、1 つの問題で非常にうまく機能しています。クライアントが接続してからログオフすると、すぐにサーバーを再起動できます。ただし、クライアントがまだ接続されていて、サーバーを閉じると、クライアントは切断されますが、ポートは X 秒間バインドされたままになります (X にはわかりません。約 20 とします)。これは、コンパイラでプログラムを終了している場合にも発生します。

閉じるときは、クライアントが離れるときに使用するのとまったく同じ関数を使用しています。

int CEpollClient::Close ()
{
    if(m_socket!=SOCKET_ERROR)
    {
    int res=::epoll_ctl (m_server_handler, EPOLL_CTL_DEL, m_socket, 0);
    _debug_message("client exits");
    _debug_message(res);
    shutdown(m_socket,SHUT_RDWR);
    ::close (m_socket);
    m_socket=SOCKET_ERROR;
    }
    return 0;
 }

これはクライアント クラスの一部であるため、クライアントが離れた後にクライアントを閉じるか、自分で初期化するかにかかわらず、まったく同じコードが呼び出されます。サーバーを閉じるときに、リスニングソケットも閉じています。

if (m_listener != SOCKET_ERROR)
{
    _debug_message("stop listener");
    code=epoll_ctl(m_epoll_handler,EPOLL_CTL_DEL,m_listener,0);
    _debug_message(code);
    shutdown(m_listener,SHUT_RDWR);
    ::close(m_listener);
    m_listener = SOCKET_ERROR;
}

誰かがアイデアを提供できますか?これはひどいものではなく、実行可能ですが、バグのように見えます。デバッグ メッセージ s の戻りコードは常に 0 (エラーなし) です。では、なぜそれが起こるのですか?

4

2 に答える 2

1

epoll関連ではなく、ソケット関連で質問します。そのソケットを再利用できない理由は、まだ TCPTIME_WAIT状態のままだからです。これは、設計による通常の動作です。通常、遅延は最大セグメント ライフタイムの 2 倍であり、どのような場合でも正しいシャットダウンを実行するための完全なラウンドトリップが可能ですが、 で設定することもできますSO_LINGER。単純SO_LINGERにもっと短いものに設定したくなるかもしれませんが、そうしないでください。通常の正常なシャットダウンを妨げる可能性があるため、このダイヤルで遊ぶことはお勧めできません。

もう 1 つのオプションは、SO_REUSEADDRsocket オプションを設定することです。これは、おそらく必要なものです。SO_REUSEADDRソケット層に、それが行う正確性の約束を忘れて、意図的に通常の操作性を壊すように指示することに注意してください。基本的に、ネットワーク ライブラリに次のように伝えています。
これはまさにあなたの例の場合です。あなたはすでにソケットを難しい方法で閉じており、それはなくなり、他の誰もそれを使用していません。あなたが気にかけているのは、できるだけ早くそれを新しく使用することだけです.

使用可能なソケット オプションの説明については、たとえば、 を参照してくださいsocket(7)

于 2014-10-24T10:43:27.320 に答える
1

システムにソケットを要求する必要があるため、ソケットを再利用できないと思います。bind(2) を呼び出す前に、次のようにします。

https://github.com/edsiper/monkey/blob/master/src/mk_socket.c#L114

役立つことを願っています。

于 2013-02-14T19:10:14.490 に答える