2

以下のサーバーコードでソケットを呼び出した後、「開いているファイルが多すぎます」というエラーが表示されます。このコードは繰り返し呼び出され、server_SD が値 1022 を取得した直後にのみ発生します。そのため、「ulimit -n」で禁止されている 1024 の制限に達していると想定しています。私が理解していないのは、ソケットを閉じていることです。これにより、fd が再利用可能になるはずですが、これは起こっていないようです。

注: Linux を使用していて、クライアントも閉じています。いいえ、私は root ユーザーではないため、制限を移動することはできません。一度に最大 20 個 (またはそれくらい) のソケットを開く必要があります。私のプログラムの存続期間中に、1000000 近くのソケットを開いたり閉じたりすることが予想されます (したがって、非常に強力に再利用する必要があります)。

  server_SD = socket (AF_INET, SOCK_STREAM, 0);  
  bind (server_SD, (struct sockaddr *) &server_address, server_len)  
  listen (server_SD,1)  
  client_SD = accept (server_SD, (struct sockaddr *)&client_address, &client_len)  
  // read, write etc...   
  shutdown (server_SD, 2);  
  close (server_SD)

閉鎖と再利用性を保証する方法を知っている人はいますか?

ありがとう。

4

6 に答える 6

2

あなたの説明から、それぞれのサーバーソケットを開いているようですaccept(2)。それは必要ありません。サーバーソケットを1回作成し、bind(2)それをループでlisten(2)呼び出します(または、さらに良いことに、に渡します)accept(2)poll(2)

編集 0:

ちなみに、shutdown(2)on listen ソケットはまったく意味がなく、接続されたソケットのみを対象としています。

于 2009-08-05T16:13:00.660 に答える
2

valgrind次の--track-fds=yesオプションを使用してプログラムを実行します。

valgrind --track-fds=yes myserver

--trace-children=yesプログラムがラッパーを使用している場合、またはそれ自体をバックグラウンドに置く場合にも必要になる場合があります。

単独で終了しない場合は、中断するか、リークされたファイル記述子が蓄積された後、プロセスを " kill pid " ( not ) で強制終了します。 -9終了時に、valgrindまだ開いているファイル記述子と、それらが作成された場所に対応するスタック トレースが表示されます。

すべてのシステムコールをログに記録するためにプログラムを実行するstraceことも役立つ場合があります。もう 1 つの便利なコマンドは/usr/sbin/lsof -p pidで、現在使用されているすべてのファイル記述子とその用途を表示します。

于 2009-08-05T19:36:43.400 に答える
0

これは、「TIME_WAIT」の問題があるようです。IIRC、TIME_WAIT は、TCP ソケットが入ることができるステータスの 1 つであり、両側が接続を閉じたときに入力されますが、システムはしばらくの間ソケットを保持し、遅延メッセージが後続の接続の適切なペイロードとして受け入れられるのを防ぎます。

これを見てください(99 ページの下部と 100 の上部)。そして多分その他の質問

于 2009-08-05T11:36:16.530 に答える
0

おそらく問題は、SO_REUSEADDR フラグを指定していないことですか?

ソケットのマンページから:

SO_REUSEADDR bind(2) 呼び出しで提供されたアドレスの検証に使用される規則が、ローカル アドレスの再利用を許可する必要があることを示します。PF_INET ソケットの場合、これは、アドレスにバインドされたアクティブな listen ソケットがある場合を除いて、ソケットがバインドできることを意味します。リスニング ソケットが特定のポートで INADDR_ANY にバインドされている場合、どのローカル アドレスでもこのポートにバインドすることはできません。

于 2009-08-05T10:54:47.567 に答える
0

を使用していfork()ますか? もしそうなら、あなたの子供は開かれたファイル記述子を継承している可能性があります。この場合、子に属していないすべての fd を閉じさせる必要があります。

于 2009-08-05T11:07:03.953 に答える
-1

サーバーを閉じる前にクライアントを閉じる必要があります(上記のコードとは逆の順序です!)
提案を提供してくれたすべての人に感謝します!

于 2009-08-05T19:34:37.617 に答える