14

listen(fd, backlog) を呼び出した後、ソケットでリッスンを解除することは可能ですか?

編集:自分自身を明確にしないという私の間違い。ソケットで一時的にリッスンを解除できるようにしたいと思います。close() を呼び出すと、ソケットが M2LS 状態のままになり、再度開くことができなくなります (さらに悪いことに、悪意のあるプログラムがそのソケットにバインドされる可能性があります)。

一時的にリッスンしないことは、アップストリームのロード バランサーに、このアプリがこれ以上リクエストを受け入れられないことを通知する方法です (最善の方法ではないかもしれません)。

4

11 に答える 11

5

ソケットを閉じた後でも、プログラムはソケットが「使用中」であると通知する場合があります。しかし、ソケットに関するマンページには、同じソケットを再利用するフラグがあり、遅延して呼び出される「SO_REUSEADDR」があることが示されています。「setsockopt()」で設定してください。

于 2008-10-02T12:03:42.343 に答える
4

一部のソケットライブラリでは、着信接続を明確に拒否できます。例:GNUのCommonC ++:TCPsocketクラスにはrejectメソッドがあります。

BSDソケットにはこの機能はありません。ソケットを開いたまま、接続を受け入れてすぐに閉じることができます。

while (running) {

  int i32ConnectFD = accept(i32SocketFD, NULL, NULL);
  while (noConnectionsPlease) {
    shutdown(i32ConnectFD, 2);
    close(i32ConnectFD);
    break;
  }

}
于 2008-10-03T21:40:38.797 に答える
4

閉じます。私が思い出すように;

close(fd);
于 2008-10-02T11:39:29.093 に答える
2

上流のロードバランサーに信号を送るのは良い方法ではないと思います。メッセージが通過する前に、実際にサーバーにいくつかの接続を送信する必要があります。これらの接続はおそらく拒否されます。

同様に、リスニングソケットを閉じたときに保留されていた接続は、データなしで閉じられます。

アップストリームのロードバランサーにシグナルを送信する場合は、そのためのプロトコルが必要です。TCPを悪用してそれを実行しようとしないでください。

幸いなことに、クライアントが通常のWebブラウザーである場合は、非常に多くのことを回避できます。ソケットを閉じるだけで、通常、ユーザーに対して透過的に(ある程度まで)再試行されます。

于 2010-08-13T15:49:17.183 に答える
2

編集した質問のバージョンに基づいて、「聞いていない」または閉じる()必要があるかどうかはわかりません。次の 2 つのオプションが思い浮かびます。

1) listen() を呼び出した後、(論理的に十分に) accept() を呼び出すまで、接続は実際には受け入れられません。ソケットのアクティビティを無視し、準備が整うまでaccept()を延期するだけで、「リッスンしない」ことができます。インバウンド接続の試みは、ポートがリッスン モードで開かれたときに作成されたキューにバックログされます。スタック内のバックログ キューがいっぱいになると、それ以降の接続試行は単純にフロアにドロップされます。accept() で再開すると、バックログをすぐにデキューし、さらに接続できるようになります。

2) ポートを一時的に完全に閉じたように見せたい場合は、カーネル レベルのパケット フィルタをポートに動的に適用して、インバウンド接続試行がネットワーク スタックに到達するのを防ぐことができます。たとえば、ほとんどの *nix プラットフォームで Berkeley Packet Filter (BPF) を使用できます。つまり、プラットフォームのファイアウォール機能を使用して、対象のポートに着信するインバウンド パケットをドロップする必要があります。もちろん、これはプラットフォームによって異なりますが、可能なアプローチです。

于 2008-10-02T21:42:30.063 に答える
1

リッスンを解除する明示的な方法はありません。

close(fd)または_shutdown(fd, how)

fd is the socket file descriptor you want to shutdown, and how is one of the following:

0 Further receives are disallowed

1 Further sends are disallowed

2 Further sends and receives are disallowed (like close())
于 2008-10-02T11:56:17.773 に答える
0

編集した質問に基づくかなり醜いアプローチは次のとおりです。

通常のバックログでリッスンするためのソケットを開きます。続行。

「シャットダウン」する場合は、バックログが1でSO_REUSEADDRの2番目のものを開きます。最初のものを閉じます。再開する準備ができたら、通常のバックログを持つソケットに別のソケットジャグリングを実行します。

閉じているソケットから受け入れキューを排出することに関する厄介な詳細は、ここでのキラーになります。おそらく、このアプローチを実行不可能にするのに十分なキラーです。

于 2008-10-03T18:07:03.673 に答える
0

質問には、どのようなソケットがあるかはわかりませんでした。UNIX ソケットの場合は、rename(2) を使用してリッスンを停止および開始できます。unlink(2) でリッスンを永久に停止することもできます。ソケットは開いたままなので、引き続きバックログを処理できます。このアプローチは非常に便利に思えますが、私はこれまで使用されたことがなく、自分で調べているところです。

于 2010-10-05T19:31:14.037 に答える
0

ソケット API を介してこれを行うことが不可能であることについて、すでにいくつかの回答を得ています。

他の OS メソッド (Host firwewall/iptables/ipfilter など) を使用して、一時的な拒否ルールを設定できます。

ほとんどのロード バランサーは、接続の問題を認識できる可能性が少し限られていることがわかりました (ほとんどのロード バランサーは、正当な接続試行に対する回答としてではなく、接続プローブでのみ RST を認識します)。

とにかく、利用できないことを検出するプローブによって制限されている場合は、HTTP 要求または FTP ログインを行うアプリケーション レベルのプローブをセットアップします。「500 サービスが利用できません」などのエラー メッセージを解釈することもできます。SNMP を使用すると、一部のロード バランサーは結果をロード ヒントとして使用することもできます。

于 2012-09-07T20:36:43.530 に答える
0

必ずしもこれが良い考えだとは思いませんが...

listen をもう一度呼び出すことができる場合があります。POSIX仕様は、そうしないとは言っていません。おそらく、「聞き取りをやめたい」場合は、backlog パラメータを 0 にして 2 回呼び出すことができます。

バックログが 0 の状態で listen が呼び出されるとどうなるかは、実装で定義されているようです。POSIX 仕様では、接続の受け入れを許可する可能性があると述べています。これは、backlog パラメーターが 0 の場合、一部の実装がすべての接続を拒否することを選択する可能性があることを意味します。 SOMAXCONN)。

于 2009-07-09T03:42:56.923 に答える
0

基本的なレベルでは、ソケットは開いているか閉じているかのいずれかです (ここでは、TCP/IP 状態図の詳細は無視します)。

ソケットが閉じている場合、何もデータを送信できません。開いている場合、受信データは TCP/IP スタックによって受け入れられ、バッファリング アルゴリズムが「十分!」と叫ぶまで確認応答されます。その時点で、それ以上のデータは確認されません。

私が見ることができるあなたには2つの選択肢があります。「リッスンを解除」したい場合はソケットを close() し、後で再オープンします - SO_REUSEADDR フラグを指定して setsockopt() を使用して、TIME_WAIT2 が期限切れになる前に既知のポートに再バインドできるようにします。

もう 1 つの選択肢は、ソケットを開いたままにしておくことですが、'忙しい' 間は単にソケットから accept() を行わないようにすることです。リクエストに対するアプリケーション レベルの確認応答があると仮定すると、ロード バランサーは応答が得られていないことを認識し、それに応じて動作します。

于 2008-10-02T21:26:21.897 に答える