読み書き操作を行う前に接続状態を確認したい。
isConnect() メソッドを作成する方法はありますか?
これを見たけど「醜い」らしい。
is_open()関数もテストしましたが、期待どおりの動作がありません。
TCP は、過酷なネットワークに直面しても堅牢であることを意図しています。TCP は永続的なエンドツーエンド接続のように見えますが、それはすべて嘘であり、各パケットは実際には一意で信頼性の低いデータグラムにすぎません。
接続は実際には、接続の両端 (送信元と送信先のポートとアドレス、およびローカル ソケット) で追跡される小さな状態で作成された単なる仮想コンジットです。ネットワーク スタックは、この状態を使用して、各着信パケットをどのプロセスに渡すか、および各発信パケットのヘッダーにどの状態を入れるかを認識します。
根底にある (本質的にコネクションレスで信頼性の低い) ネットワークの性質のため、スタックは、リモート エンドが接続を閉じるために FIN パケットを送信する場合、または送信されたパケットに対する ACK 応答を受信しない場合にのみ、切断された接続を報告します。 (タイムアウトと数回の再試行の後)。
asio の非同期性のため、適切な切断を通知する最も簡単な方法は、接続が閉じられるとすぐにasync_read
返される未処理を用意することです。error::eof
しかし、これだけでも、ハーフオープン接続やネットワークの問題が検出されないなど、他の問題が発生する可能性が残ります.
予期しない接続の中断を回避する最も効果的な方法は、何らかのキープアライブまたは ping を使用することです。接続を介してデータを転送しようとするこの時折の試みにより、意図せずに切断された接続を迅速に検出できます。
TCP プロトコルには、実際には組み込みのキープアライブ メカニズムがあり、 を使用して asio で設定できますasio::tcp::socket::keep_alive
。TCP キープアライブの優れた点は、それがユーザー モード アプリケーションに対して透過的であり、キープアライブに関心のあるピアだけがそれを構成する必要があることです。欠点は、タイムアウト パラメータを設定するには OS レベルのアクセス/知識が必要なことです。残念ながら、それらは単純なソケット オプションを介して公開されておらず、通常、デフォルトのタイムアウト値は非常に大きくなっています (Linux では 7200 秒)。
おそらくキープアライブの最も一般的な方法は、アプリケーション層に実装することです。この層では、アプリケーションは特別な noop または ping メッセージを持ち、くすぐられたときに応答するだけです。この方法により、キープアライブ戦略を実装する際の柔軟性が最も高くなります。
TCP は、ドロップされたパケットを監視することを約束し (必要に応じて再試行します)、信頼できる接続を提供します。もちろん、TCP は、サーバーがクラッシュしたり、イーサネット ケーブルが脱落したり、同様のことが発生した場合には対応できません。さらに、TCP 接続が確立されていることを知っていても、必ずしも TCP 接続を経由するプロトコルの準備ができているとは限りません (たとえば、HTTP Web サーバーまたは FTP サーバーが壊れた状態にある可能性があります)。
TCP 経由で送信されているプロトコルがわかっている場合は、そのプロトコルに、状態が良好かどうかを通知する方法がある可能性があります (HTTP の場合はHEAD リクエストになります) 。
ソケットにダミー バイトを送信して、エラーが返されるかどうかを確認できます。