現在、いくつかのWebサーバーソフトウェアを保守しており、多くのI/O操作を実行する必要があります。 read()
、write()
、close()
、およびshutdown()
呼び出しをソケットで使用すると、ENOTCONN
が発生する場合があります。エラー。このエラーは正確にはどういう意味ですか?それを引き起こす条件は何ですか?ローカルで再現することはできないようですが、再現できるユーザーもいます。
今のところ、close()
とshutdown()
によって発生したENOTCONN
は無害に見えるので無視しますが、完全にはわかりません。
編集:
connect()
呼び出しが成功したことは間違いありません。戻り値を確認します。ENOTCONN
は、ほとんどの場合、close()
およびshutdown()
によって発生します。 read()
とwrite()
がENOTCONN
を上げるのはめったに見たことがありません。TCP接続のどちら側でも接続が閉じられていないことが確実な場合は、リモート側が接続を閉じているように聞こえます。
ENOTCONN
は、他の人が指摘しているように、単にソケットが接続されていないことを意味します。これは、必ずしもconnect
が失敗したことを意味するわけではありません。ソケットは以前に接続されていた可能性がありますが、呼び出しの時点では接続されていなかったため、ENOTCONN
になりました。
これは次とは異なります。
ECONNRESET
:接続のもう一方の端がTCPリセットパケットを送信しました。これは、もう一方の端が接続を拒否している場合、またはすでに接続されていることを確認していない場合に発生する可能性があります、 とりわけ。ETIMEDOUT
:これは通常connect
にのみ適用されます。これは、システムに依存する時間内に接続の試行が成功しなかった場合に発生する可能性があります。EPIPE
は、ENOTCONN
とほぼ同じ条件下で、ソケット関連のシステムコールによって返される場合があります。たとえば、一部のシステムでは、EPIPE
とENOTCONN
はsend
によって返されるときに同義です。
shutdown
がENOTCONN
を返すことは珍しいことではありませんが、この関数はTCP接続を切断することになっているので、close
return ENOTCONN
。実際にはそうすべきではありません。
最後に、dwcが述べたように、すでにEBADF
dされているファイル記述子に対して何らかの操作を試みない限り、close
はシナリオに適用されるべきではありません。ソケットを切断する(つまり、TCP接続が切断された))ことは、そのソケットに関連付けられているファイル記述子を閉じることと同じではありません。
これは、ソケットをshutting()した時点で、受信ソケットをclosed()またはshutdown()したリモートパーティに配信されるのを待っているデータがソケットのバッファにあるためです。私はソケットがどのように機能するかを理解し終えていません、私はむしろ初心者であり、この「シャットダウン」機能が実装されているファイルを見つけることさえできませんでしたが、私が始めたソケット全体のユーザーマニュアルが実質的にないことがわかりました「制御された」環境でエラーが発生するまで、すべての可能性を試しました。それは他の何かかもしれませんが、これらを何度も試した後、私が解決した説明は次のとおりです。
Shutdown()がECONNRESETまたはその他のより正確なエラーを返すことは想定されていないため、ENOTCONNが返されると思います。
反対側が「ちょうど」接続を閉じたと考えるのは誤りです。 TCPレベルでは、反対側は接続を半分しか閉じることができません(または接続を中止できます)。両側がshutdown()(またはclose())を実行すると、接続は通常完全に閉じられます。両方がそれを行う場合、shutdown()は実際には両方に対して成功します!
問題は、shutdown()が接続を通常の(半分)閉じることに成功しなかったnotであり、最初に接続を閉じたときでも、二つ目。 – shutdown()のPOSIXドキュメントにリストされているエラーから、ENOTCONNは最も不適切ではありません。他のエラーは、shutdown()に渡される引数の問題(または要求を処理するためのローカルリソースの問題)を示しているためです。
どうしたの?最近では、関係する2つのパーティ間のどこかにあるNATデバイスが関連付けをドロップし、反応としてRESETパケットを送信している可能性があります。リセット接続はIPv4で非常に一般的であるため、どこでも取得できます。あなたのコードは、shutdown()でENOTCONNとしてマスクされていても。
コーディングのバグも原因かもしれません。たとえば、非ブロッキングソケットでは、connect()は、接続が成功したことを示すことなく0を返すことができます。
トランスポートエンドポイントが接続されていません
ソケットはコネクション型プロトコルに関連付けられており、接続されていません。これは通常、プログラミングの欠陥です。
そもそも正しく接続していると確信している場合、ENOTCONN
は、あなたの側でfd
が閉じられている(おそらく別のスレッドで?)ことが原因である可能性があります。 'リクエストの途中、またはリクエストの途中で接続が切断された。
いずれにせよ、それはソケットが接続されていないことを意味します。先に進み、そのソケットをクリーンアップします。死んだ。 close()
またはshutdown()
を呼び出しても問題ありません。