1

パケット配信が永続的に失敗した場合、TCP/IP はどのようにエラーを報告しますか? 私が見たすべての Socket.write() API は、基礎となる TCP/IP 出力バッファーにバイトを渡し、データを非同期に転送するだけです。では、パケット配信が永続的に失敗した場合 (つまり、宛先ホストに到達できなくなった場合)、TCP/IP はどのように開発者に通知することになっているのでしょうか?

送信者がリモート エンドからの確認を待つ必要があるプロトコルでは、エラー メッセージが表示されます。しかし、送信者が宛先からバイトを読み取る必要がないプロトコルの場合はどうなるでしょうか? TCP/IP は黙って失敗するだけですか? おそらく Socket.close() はエラーを返しますか? TCP/IP 仕様はこれについて何か述べていますか?

4

4 に答える 4

5

TCP/IP は、信頼性の高いバイト ストリーム プロトコルです。すべてのバイトが受信者に到達するか、エラーが表示されます。

エラー表示は、閉じたソケットの形で表示されます。通信パターン (誰が送信するか) に関係なく、バイトを配信できない場合、ソケットは閉じます。

問題は、ソケットが閉じているのをどのように見るかということです。読んでいない場合は、最終的に閉じたソケットに書き込もうとしてエラーが発生します(ECONNRESET errnoを使用すると思います)。

別のファイルハンドルの入力をスリープまたは待機する必要がある場合は、待機しているソースのリストにソケットを含める select() 呼び出しで待機することをお勧めします (予期しない場合でも)。何でも受け取る)。select() がソケットが読み取り呼び出しの準備ができていることを示している場合、-1 が返されることがあります (ECONNRESET を使用すると思います)。EOF は、正常な終了を示します (反対側が shutdown() または close() を実行しました)。

このエラー クローズとクリーン クローズ (たとえば、他のプログラムの終了) を区別する方法は? errno 値は、エラーと通常の終了を区別するのに十分な場合があります。

問題を明確に示したい場合は、おそらく、ソケット層の上にある種のアプリケーション レベルのプロトコルを構築する必要があります。たとえば、受信者から送信者に返される短い「ack」メッセージ。次に、その上位レベルのアプリケーション プロトコルの違反 (送信者が ack を確認しなかった) は、それがエラー クローズとクリーン クローズであったことの確認になります。

于 2008-10-08T04:14:28.483 に答える
4

ソケット API には、ピアによって確認された受信バイト数を正確にライターに通知する方法がありません。shutdown成功またはそのいずれかの存在によって行われる保証はありませんclose

TCP/IP 仕様は、アプリケーション インターフェイス (ほとんどの場合、ソケット API) について何も述べていません。

SCTPは、特にこれらの欠点に対処しようとする TCP の代替手段です。

于 2008-10-08T04:02:50.177 に答える
0

TCPは、インターネットの中心となるIPプロトコルに基づいて構築されており、ルーティングを駆動する相互運用性の多くを提供します。ルーティングは、送信元から宛先へのパケットの取得方法を決定するものです。IPプロトコルは、パケットが送信者に到達できない場合に、インターネット制御メッセージプロトコル(ICMP)を介してエラーメッセージを送信者に送り返す必要があることを指定しています。これらの理由のいくつかには、Time To Live(TTL)フィールドがゼロにデクリメントされることが含まれます。これは、多くの場合、パケットがルーティングループでスタックしたか、スイッチの競合が原因でパケットがドロップされてバッファオーバーランが発生したことを意味します。他の人が言っているように、IP層でこれらのエラーをTCP層でネットワークと相互作用するアプリケーションまで中継するために使用されているのはSocketAPIの責任です。

于 2008-10-08T04:30:34.677 に答える
0

C では、send() で失敗したソケットに書き込むと、送信されたバイト数が返されます。これが送信しようとしていたバイト数と一致しない場合は、問題があります。また、失敗したソケットに書き込むと、SIGPIPE が返されます。ソケット処理を開始する前に、SIGPIPE を取得したときに警告するシグナル ハンドラーを配置する必要があります。

ソケットから読み取る場合は、タイムアウトできるようにアラームでラップする必要があります。「alarm(timeout_val); recv(); alarm(0)」のように。recv のリターン コードを確認し、0 の場合は、接続が閉じられたことを示します。負の戻り結果は読み取りの失敗を示し、errno を確認する必要があります。

于 2008-10-08T04:09:42.487 に答える