web-dev-qa-db-ja.com

ENOTCONNエラーの原因は何ですか?

現在、いくつかのWebサーバーソフトウェアを保守しており、多くのI/O操作を実行する必要があります。 read()write()close()、およびshutdown()呼び出しをソケットで使用すると、ENOTCONNが発生する場合があります。エラー。このエラーは正確にはどういう意味ですか?それを引き起こす条件は何ですか?ローカルで再現することはできないようですが、再現できるユーザーもいます。

今のところ、close()shutdown()によって発生したENOTCONNは無害に見えるので無視しますが、完全にはわかりません。

編集:

  • connect()呼び出しが成功したことは間違いありません。戻り値を確認します。
  • ENOTCONNは、ほとんどの場合、close()およびshutdown()によって発生します。 read()write()ENOTCONNを上げるのはめったに見たことがありません。
17
Hongli

TCP接続のどちら側でも接続が閉じられていないことが確実な場合は、リモート側が接続を閉じているように聞こえます。

ENOTCONNは、他の人が指摘しているように、単にソケットが接続されていないことを意味します。これは、必ずしもconnectが失敗したことを意味するわけではありません。ソケットは以前に接続されていた可能性がありますが、呼び出しの時点では接続されていなかったため、ENOTCONNになりました。

これは次とは異なります。

  • ECONNRESET:接続のもう一方の端がTCPリセットパケットを送信しました。これは、もう一方の端が接続を拒否している場合、またはすでに接続されていることを確認していない場合に発生する可能性があります、 とりわけ。
  • ETIMEDOUT:これは通常connectにのみ適用されます。これは、システムに依存する時間内に接続の試行が成功しなかった場合に発生する可能性があります。

EPIPEは、ENOTCONNとほぼ同じ条件下で、ソケット関連のシステムコールによって返される場合があります。たとえば、一部のシステムでは、EPIPEENOTCONNsendによって返されるときに同義です。

shutdownENOTCONNを返すことは珍しいことではありませんが、この関数はTCP接続を切断することになっているので、close return ENOTCONN。実際にはそうすべきではありません。

最後に、dwcが述べたように、すでにEBADFdされているファイル記述子に対して何らかの操作を試みない限り、closeはシナリオに適用されるべきではありません。ソケットを切断する(つまり、TCP接続が切断された))ことは、そのソケットに関連付けられているファイル記述子を閉じることと同じではありません。

18
Dan Moulding

これは、ソケットをshutting()した時点で、受信ソケットをclosed()またはshutdown()したリモートパーティに配信されるのを待っているデータがソケットのバッファにあるためです。私はソケットがどのように機能するかを理解し終えていません、私はむしろ初心者であり、この「シャットダウン」機能が実装されているファイルを見つけることさえできませんでしたが、私が始めたソケット全体のユーザーマニュアルが実質的にないことがわかりました「制御された」環境でエラーが発生するまで、すべての可能性を試しました。それは他の何かかもしれませんが、これらを何度も試した後、私が解決した説明は次のとおりです。

  • リモート側が接続を閉じた後にデータを送信した場合、shutdown()を実行すると、エラーが発生します。
  • リモート側が接続を閉じる前にデータを送信したが、もう一方の端で受信()されなかった場合は、一度shutdown()を実行できます。次にshutdown()を試行すると、エラーが発生します。
  • データを送信しなかった場合は、リモート側がshutdown()しない限り、いつでもシャットダウンできます。リモート側がshutdown()を実行した後、shutdown()を試行し、ソケットがすでにshutdown()されている場合、エラーが発生します。
1
guest

Shutdown()がECONNRESETまたはその他のより正確なエラーを返すことは想定されていないため、ENOTCONNが返されると思います。

反対側が「ちょうど」接続を閉じたと考えるのは誤りです。 TCPレベルでは、反対側は接続を半分しか閉じることができません(または接続を中止できます)。両側がshutdown()(またはclose())を実行すると、接続は通常完全に閉じられます。両方がそれを行う場合、shutdown()は実際には両方に対して成功します!

問題は、shutdown()が接続を通常の(半分)閉じることに成功しなかったnotであり、最初に接続を閉じたときでも、二つ目。 – shutdown()のPOSIXドキュメントにリストされているエラーから、ENOTCONNは最も不適切ではありません。他のエラーは、shutdown()に渡される引数の問題(または要求を処理するためのローカルリソースの問題)を示しているためです。

どうしたの?最近では、関係する2つのパーティ間のどこかにあるNATデバイスが関連付けをドロップし、反応としてRESETパケットを送信している可能性があります。リセット接続はIPv4で非常に一般的であるため、どこでも取得できます。あなたのコードは、shutdown()でENOTCONNとしてマスクされていても。

コーディングのバグも原因かもしれません。たとえば、非ブロッキングソケットでは、connect()は、接続が成功したことを示すことなく0を返すことができます。

1
Robert Siemer

トランスポートエンドポイントが接続されていません

ソケットはコネクション型プロトコルに関連付けられており、接続されていません。これは通常、プログラミングの欠陥です。

差出人: http://www.wlug.org.nz/ENOTCONN

0

そもそも正しく接続していると確信している場合、ENOTCONNは、あなたの側でfdが閉じられている(おそらく別のスレッドで?)ことが原因である可能性があります。 'リクエストの途中、またはリクエストの途中で接続が切断された。

いずれにせよ、それはソケットが接続されていないことを意味します。先に進み、そのソケットをクリーンアップします。死んだ。 close()またはshutdown()を呼び出しても問題ありません。

0
dwc