彼らは、システムの誤動作を理解するまで、システムを完全に理解できないと言います。 学生として、私はTCPの実装を楽しみのために書き、その後ITで数年間働きましたが、それでもTCPの仕事とそのエラーについてさらに深く研究し続けています。 最も驚くべきことは、これらのエラーの一部が基本的なものに現れることです。 そして、それらは明らかではありません。 この記事では、それらをCar Talkまたは古いJavaパズルのスタイルのパズルとして提示します 。 他の優れたパズルと同様に、それらは非常に簡単に再現できますが、解決策は通常驚くべきものです。 そして、神秘的な詳細に注意を向ける代わりに、これらのパズルは、TCPの基本原理のいくつかを学ぶのに役立ちます。
前提条件
これらのパズルは、UnixのようなシステムでのTCPの基本的な知識を暗示しています。 しかし、それらを掘り下げるためにマスターになる必要はありません。 例:
- TCPセッションの状態、接続の3つの段階、およびその完了の段階に関する情報は、 Wikipediaで見つけることができます。
- プログラムは通常、
read
、write
、connect
、bind
、listen
およびaccept
を使用してソケットと対話します。 さらに、send
およびrecv
もありsend
が、この例ではread
およびwrite
ように動作しwrite
。 - この記事では
poll
を使用します。 多くのシステムはkqueue
やepoll
などのより効率的なものを使用しますが、このタスクではこれらのツールはすべて同等です。 これらのメカニズムではなく、ブロッキング操作を使用するアプリケーションに関しては、TCPエラーがpoll
どのように影響するかを理解すると、ブロッキング操作にどのような影響があるかを推測しやすくなります。
これらの例をすべて自分で繰り返すことができます。 VMware Fusionを使用して実行している2つの仮想マシンを使用しました。 結果は、運用サーバーと同じです。 テストでは、SmartOSで
nc(1)
を使用しましたが、再現可能な問題が特定のOSに固有のものになるとは思いません。 システムコールを追跡し、大まかなタイミング情報を収集するために、illumosプロジェクトのtruss(1)ユーティリティを使用しました。 この情報は、OS Xのdtruss(1m)またはGNU / Linuxのstrace(1)で取得できます。
nc(1)
非常に単純なプログラムです。 次の2つのモードで使用します。
- サーバーのように。 このモードでは、ncはソケットを作成してリッスンし、
accept
を呼び出して接続が確立されるまでブロックします。 - 顧客として。 このモードでは、
nc
はソケットを作成し、リモートサーバーへの接続を確立します。
両方のモードで、接続が確立された後、各側は
poll
を使用して標準入力を待機するか、読み取り準備ができているデータのあるソケットを接続します。 着信データが端末に出力されます。 端末に入力したデータは、ソケットを介して送信されます。 CTRL-Cを押すと、ソケットが閉じてプロセスが停止します。
例では、クライアントは
kang
と呼ばれ、サーバーは
kodos
と呼ばれ
kodos
。
ウォームアップ:通常のTCPブレーク
基本的な状況から始めましょう。
kodos
サーバーを構成したと想像して
kodos
:
サーバー
[root@kodos ~]# truss -d -t bind,listen,accept,poll,read,write nc -l -p 8080 Base time stamp: 1464310423.7650 [ Fri May 27 00:53:43 UTC 2016 ] 0.0027 bind(3, 0x08065790, 32, SOV_SOCKBSD) = 0 0.0028 listen(3, 1, SOV_DEFAULT) = 0 accept(3, 0x08047B3C, 0x08047C3C, SOV_DEFAULT, 0) (sleeping...)
(これらの例では、
nc
が行うシステムコールを出力するために
truss
を使用していることを思い出します。時間情報は
truss
フラグを使用して表示されます。
次に、
kang
接続を確立します。
お客様
[root@kang ~]# truss -d -t connect,pollsys,read,write,close nc 10.88.88.140 8080 Base time stamp: 1464310447.6295 [ Fri May 27 00:54:07 UTC 2016 ] ... 0.0062 connect(3, 0x08066DD8, 16, SOV_DEFAULT) = 0 pollsys(0x08045670, 2, 0x00000000, 0x00000000) (sleeping...)
kodos
は以下が表示されます。
サーバー
23.8934 accept(3, 0x08047B3C, 0x08047C3C, SOV_DEFAULT, 0) = 4 pollsys(0x08045680, 2, 0x00000000, 0x00000000) (sleeping...)
TCP接続はESTABLISHED状態にあり、両方のプロセスは
poll
ます。
netstat
を使用して、すべてのシステムでこれを確認できます。
サーバー
[root@kodos ~]# netstat -f inet -P tcp -n TCP: IPv4 Local Address Remote Address Swind Send-Q Rwind Recv-Q State –––––––––––––––––––– –––––––––––––––––––– ––––– –––––- ––––– –––––- ––––––––––- 10.88.88.140.8080 10.88.88.139.33226 1049792 0 1049800 0 ESTABLISHED ...
お客様
[root@kang ~]# netstat -f inet -P tcp -n TCP: IPv4 Local Address Remote Address Swind Send-Q Rwind Recv-Q State –––––––––––––––––––– –––––––––––––––––––– ––––– –––––- ––––– –––––- ––––––––––- 10.88.88.139.33226 10.88.88.140.8080 32806 0 1049800 0 ESTABLISHED ...
質問: プロセスの1つを完了すると、他のプロセスはどうなりますか? 彼は何が起こったのか理解できますか? 彼はこれをどのように理解しますか? 特定のシステムコールの動作を予測し、それぞれがそれを行う理由を説明してみましょう。
kodos
CTRL-Cを
kodos
ます。
サーバー
pollsys(0x08045680, 2, 0x00000000, 0x00000000) (sleeping...) ^C127.6307 Received signal #2, SIGINT, in pollsys() [default]
そして、これが
kang
に見られるものです:
お客様
pollsys(0x08045670, 2, 0x00000000, 0x00000000) (sleeping...) 126.1771 pollsys(0x08045670, 2, 0x00000000, 0x00000000) = 1 126.1774 read(3, 0x08043670, 1024) = 0 126.1776 close(3) = 0 [root@kang ~]#
どうした それを理解しましょう:
- プロセスを終了するときに、SIGINTをサーバーに送信しました。 終了後、ファイル記述子は閉じられました。
-
ESTABLISHED
ソケットの最後のハンドルが閉じられると、TCPスタックはFIN接続を介してkodos
送信し、FIN_WAIT_1
入ります。 -
kang
上のTCPスタックはFINパケットを受信し、自身の接続をCLOSE_WAIT
状態CLOSE_WAIT
、応答としてACKを送信します。nc
クライアントがソケットをブロックしている間-読み取りの準備ができている間、カーネルはPOLLIN
を使用してこのスレッドをPOLLIN
ます。 -
nc
クライアントは、ソケットのPOLLIN
をPOLLIN
し、read
を呼び出しread
。これはすぐに0を返します。これは、接続の終了を意味します。nc
は、ソケットの処理が完了したと判断し、閉じます。 - それまでの間、
kodos
上のTCPスタックはACKを受信し、FIN_WAIT_2
入りFIN_WAIT_2
。 - kangの
nc
クライアントがソケットを閉じる間、kangのTCPスタックはFINをkodos
送信しkodos
。kang
の接続はLAST_ACK
状態に入ります。 -
kodos
のTCPスタックはFINを受信し、接続はTIME_WAIT
状態になり、kodos
のスタックはFINを確認します。 -
kang
のTCPスタックはFINのACKを受信し、接続を完全に削除します。 - 2分後、
kodos
のTCP接続は閉じられ、スタックは接続を完全に削除します。
手順の順序はわずかに異なる場合があります。 また、
kang
は、
FIN_WAIT_2
代わりに、
CLOSING
状態になる場合があります。
したがって、netstatによると、最終状態は次のようになります。
サーバー
[root@kodos ~]# netstat -f inet -P tcp -n TCP: IPv4 Local Address Remote Address Swind Send-Q Rwind Recv-Q State –––––––––––––––––––– –––––––––––––––––––– ––––– –––––- ––––– –––––- ––––––––––- 10.88.88.140.8080 10.88.88.139.33226 1049792 0 1049800 0 TIME_WAIT
この接続の
kang
は送信データはありません。
中間状態は非常に迅速に通過しますが、 DTrace TCPプロバイダーを使用して追跡できます 。 パケットフローは、 snoop(1m)またはtcpdump(1)を使用して表示できます。
結論:接続のインストールおよび終了中にシステムコールを渡す通常の方法を見ました。
kang
は、接続が
kodos
で閉じられたという事実をすぐに発見したことに注意してください
kodos
から起こされ
read
ゼロの
read
返すと、ストリームの終わりを
read
ます。 この時点で、
kang
はソケットを閉じることに決め 、それにより
kodos
への接続が
kodos
られ
kodos
。 後でこれに戻り、この状況で
kang
がソケットを閉じなかった場合にどうなるかを見ていきます。
パズル1:電源再起動
いずれかのシステムの電源が再起動すると、確立された非アクティブなTCP接続はどうなりますか?
スケジュールされた再起動中に多くのプロセスが(「reboot」コマンドを使用して)正しく終了するため、CTRL-Cを使用
kodos
てサーバーを
kodos
コンソールで「reboot」コマンドを入力しても同じ結果になります。 しかし、前の例で
kodos
の電源を
kodos
どうなりますか? 最終的に、
kang
はそうするでしょう?
見てみましょう。 接続を確立します。
サーバー
[root@kodos ~]# truss -d -t bind,listen,accept,poll,read,write nc -l -p 8080 Base time stamp: 1464312528.4308 [ Fri May 27 01:28:48 UTC 2016 ] 0.0036 bind(3, 0x08065790, 32, SOV_SOCKBSD) = 0 0.0036 listen(3, 1, SOV_DEFAULT) = 0 0.2518 accept(3, 0x08047B3C, 0x08047C3C, SOV_DEFAULT, 0) = 4 pollsys(0x08045680, 2, 0x00000000, 0x00000000) (sleeping...)
お客様
[root@kang ~]# truss -d -t open,connect,pollsys,read,write,close nc 10.88.88.140 8080 Base time stamp: 1464312535.7634 [ Fri May 27 01:28:55 UTC 2016 ] ... 0.0055 connect(3, 0x08066DD8, 16, SOV_DEFAULT) = 0 pollsys(0x08045670, 2, 0x00000000, 0x00000000) (sleeping...)
電源の再起動をシミュレートするには、VMwareの再起動機能を使用します。 これは実際の再起動になることに注意してください-段階的なシャットダウンにつながるものはすべて、最初の例に似ています。
20分後、
kang
まだ同じ状態にあります。
お客様
pollsys(0x08045670, 2, 0x00000000, 0x00000000) (sleeping...)
TCPの仕事は、複数のシステム間で常に抽象化(つまり、TCP接続)を維持することであると考えがちであるため、このような壊れた抽象化のケースは驚くほどに見えます。 そして、これがなんらかのnc(1)問題だと思うなら、あなたは間違っています。
kodos
「
kodos
」は
kang
への接続を表示しませんが、
kang
は
kodos
への完全に機能する接続を
kodos
ます。
お客様
[root@kang ~]# netstat -f inet -P tcp -n TCP: IPv4 Local Address Remote Address Swind Send-Q Rwind Recv-Q State –––––––––––––––––––– –––––––––––––––––––– ––––– –––––- ––––– –––––- ––––––––––- 10.88.88.139.50277 10.88.88.140.8080 32806 0 1049800 0 ESTABLISHED ...
そのままにしておくと、
kang
は
kodos
リブートされたことを知ることができません。
kang
kodos
データを送信しようとして
kang
とします。 どうなるの?
お客様
pollsys(0x08045670, 2, 0x00000000, 0x00000000) (sleeping...) kodos, are you there? 3872.6918 pollsys(0x08045670, 2, 0x00000000, 0x00000000) = 1 3872.6920 read(0, " kodos , are y".., 1024) = 22 3872.6924 write(3, " kodos , are y".., 22) = 22 3872.6932 pollsys(0x08045670, 2, 0x00000000, 0x00000000) = 1 3872.6932 read(3, 0x08043670, 1024) Err#131 ECONNRESET 3872.6933 close(3) = 0 [root@kang ~]#
メッセージを入力してEnterを押すと、
kodos
起動し、stdinからメッセージを読み取り、ソケット経由で送信します。
write
呼び出し が正常に完了しました !
nc
は、次のイベントを待機する
poll
戻り、最後に、ブロックせずにソケットを読み取ることができないと結論付け、readを呼び出し
read
。 この時間の
read
は、ECONNRESETステータスで低下します。 これはどういう意味ですか? read(2)のドキュメントには次のことが記載されています 。
[ECONNRESET] , .
別のソースには、もう少し詳細が含まれています。
ECONNRESET filedes . . / filedes.
このエラーは、
read
呼び出しに関する特定の問題を意味するものではありません。 ソケットが切断されたというだけです。 このため、ほとんどのソケット操作はエラーになります。
それで何が起こったのですか? その時点で、
kang
上の
nc
がデータを送信しようとしたとき、TCPスタックはまだ接続がすでに停止していることを知りませんでした。
kang
はデータパケットを
kodos
に送信しました
kodos
は接続について何も知らなかったため、RSTで応答しました。
kang
はRSTを見て、切断されました。 ソケットファイル記述子を閉じることはできません—ファイル記述子はこの方法では動作しませんが、その後の操作は、
nc
がファイル記述子を閉じるまでECONNRESETステータスで失敗します。
結論:
- 激しい停電は、きちんとしたシャットダウンとは大きく異なります。 分散システムをテストする場合、このシナリオは個別に確認する必要があります。 すべてが通常のプロセスのシャットダウン(kill)と同じになるとは思わないでください。
- 一方の側がTCP接続が確立されていることを確認し、もう一方の側が不明である状況があり、この状況は決して自動的に解決されません。 アプリケーションレベルまたはTCPでの接続のキープアライブを使用して、このような問題の解決を管理できます。
-
kang
がまだリモート側の消失を発見した唯一の理由は、彼がデータを送信し、接続がないことを示す応答を受信したためです。
問題は、何らかの理由で
kodos
がデータの送信に応答しない場合はどうでしょうか?
パズル2:電源オフ
TCP接続のエンドポイントがしばらくネットワークから切断されるとどうなりますか? 他のノードはこれについて知るでしょうか? もしそうなら、どのように? そしていつ?
nc
を使用して再接続します。
サーバー
[root@kodos ~]# truss -d -t bind,listen,accept,poll,read,write nc -l -p 8080 Base time stamp: 1464385399.1661 [ Fri May 27 21:43:19 UTC 2016 ] 0.0030 bind(3, 0x08065790, 32, SOV_SOCKBSD) = 0 0.0031 listen(3, 1, SOV_DEFAULT) = 0 accept(3, 0x08047B3C, 0x08047C3C, SOV_DEFAULT, 0) (sleeping...) 6.5491 accept(3, 0x08047B3C, 0x08047C3C, SOV_DEFAULT, 0) = 4 pollsys(0x08045680, 2, 0x00000000, 0x00000000) (sleeping...)
お客様
[root@kang ~]# truss -d -t open,connect,pollsys,read,write,close nc 10.88.88.140 8080 Base time stamp: 1464330881.0984 [ Fri May 27 06:34:41 UTC 2016 ] ... 0.0057 connect(3, 0x08066DD8, 16, SOV_DEFAULT) = 0 pollsys(0x08045670, 2, 0x00000000, 0x00000000) (sleeping...)
ここで、突然
kodos
の電源をオフにし、
kang
データを送信しようとします。
お客様
pollsys(0x08045670, 2, 0x00000000, 0x00000000) (sleeping...) 114.4971 pollsys(0x08045670, 2, 0x00000000, 0x00000000) = 1 114.4974 read(0, "\n", 1024) = 1 114.4975 write(3, "\n", 1) = 1 pollsys(0x08045670, 2, 0x00000000, 0x00000000) (sleeping...)
write
呼び出しは正常に終了し、私は長い間何も見ていません。 わずか5分後に表示されます。
お客様
pollsys(0x08045670, 2, 0x00000000, 0x00000000) (sleeping...) 425.5664 pollsys(0x08045670, 2, 0x00000000, 0x00000000) = 1 425.5665 read(3, 0x08043670, 1024) Err#145 ETIMEDOUT 425.5666 close(3) = 0
この状況は、電源を完全にオフにするのではなく、電源を再起動した場合と非常に似ています。 2つの違いがあります。
- システムが状況を理解するのに5分かかりました。
- エラーステータスはETIMEDOUTでした。
繰り返しますが、これは期限切れの
read
タイムアウトです。 他のソケット操作でも同じエラーが発生します。 これは、接続がタイムアウトしたときにソケットが状態に入るためです。 この理由は、このシステムの設定に応じて、リモート側が長すぎる-5分間データパケットを確認しなかったためです。
結論:
- リモートシステムが電源を再起動する代わりに、単にシャットダウンするとき、最初のシステムはデータを送信することによってのみこれを知ることができます。 さもなければ、彼女は壊れた接続について決して知ることができません。
- システムが長すぎるデータを送信しようとして応答を受信しない場合、TCP接続は閉じられ、ソケットを使用するすべての操作はETIMEDOUTエラーで終了します。
パズル3:落下せずに接続の欠如
今回は、特定の状況を説明して何が起こっているのかを尋ねる代わりに、反対のことを行います。特定の観察を説明し、これがどのように起こったかを理解できるかどうかを確認します。
kang
が
kodos
に接続していると信じているかもしれないが、
kodos
はそれについて知らないいくつかの状況を議論しました。
kodos
が
kodos
に接続されて、
kodos
が無期限にそれを知らないように
kang
ことは可能ですか(つまり、問題自体は解決されません)、停電や再起動、他の
kodos
オペレーティングシステム
kodos
、ネットワーク機器?
ヒント:接続がESTABLISHEDステータスのままである場合、上記のケースを考慮してください。 ソケットを開いたままにして、接続が中断されたときにデータを送信することで検出できるため、この問題を解決するのはアプリケーションの責任であると言えます。 しかし、アプリケーションがソケットを開いたままにしないとどうなりますか?
ウォームアップでは、
kodos
ncがソケットを閉じた状況を調べました。
kang
ncは0(転送の終了へのポインタ)を読み取り、ソケットを閉じたと言いました。 ソケットが開いたままだとしましょう。 明らかに、それから読むことは不可能でしょう。 ただし、TCPについては、FINが送信した相手に追加のデータを送信できないとは言われていません。 FINは、FINが送信された方向のデータストリームのみを閉じることを意味します。
これを実証するために、
kang
nc
を使用することはできません。0を受け取った後にソケットを自動的に閉じるためです。したがって、このポイントをスキップするdncという
nc
デモバージョンを作成しました。 Dncはまた、システムコールを明示的に表示します。 これにより、TCPのステータスを追跡する機会が得られます。
まず、接続を構成します。
サーバー
[root@kodos ~]# truss -d -t bind,listen,accept,poll,read,write nc -l -p 8080 Base time stamp: 1464392924.7841 [ Fri May 27 23:48:44 UTC 2016 ] 0.0028 bind(3, 0x08065790, 32, SOV_SOCKBSD) = 0 0.0028 listen(3, 1, SOV_DEFAULT) = 0 accept(3, 0x08047B2C, 0x08047C2C, SOV_DEFAULT, 0) (sleeping...) 1.9356 accept(3, 0x08047B2C, 0x08047C2C, SOV_DEFAULT, 0) = 4 pollsys(0x08045670, 2, 0x00000000, 0x00000000) (sleeping...)
お客様
[root@kang ~]# dnc 10.88.88.140 8080 2016-05-27T08:40:02Z: establishing connection 2016-05-27T08:40:02Z: connected 2016-05-27T08:40:02Z: entering poll()
次に、接続が両側でESTABLISHEDステータスになっていることを確認します。
サーバー
[root@kodos ~]# netstat -f inet -P tcp -n TCP: IPv4 Local Address Remote Address Swind Send-Q Rwind Recv-Q State –––––––––––––––––––– –––––––––––––––––––– ––––– –––––- ––––– –––––- ––––––––––- 10.88.88.140.8080 10.88.88.139.37259 1049792 0 1049800 0 ESTABLISHED
お客様
[root@kang ~]# netstat -f inet -P tcp -n TCP: IPv4 Local Address Remote Address Swind Send-Q Rwind Recv-Q State –––––––––––––––––––– –––––––––––––––––––– ––––– –––––- ––––– –––––- ––––––––––- 10.88.88.139.37259 10.88.88.140.8080 32806 0 1049800 0 ESTABLISHED
kodos
、
nc
プロセスにCTRL-Cを適用します。
サーバー
pollsys(0x08045670, 2, 0x00000000, 0x00000000) (sleeping...) ^C[root@kodos ~]#
kang
では、次のことがすぐにわかります。
お客様
2016-05-27T08:40:12Z: poll returned events 0x0/0x1 2016-05-27T08:40:12Z: reading from socket 2016-05-27T08:40:12Z: read end-of-stream from socket 2016-05-27T08:40:12Z: read 0 bytes from socket 2016-05-27T08:40:12Z: entering poll()
次に、TCP接続のステータスを見てみましょう。
サーバー
[root@kodos ~]# netstat -f inet -P tcp -n TCP: IPv4 Local Address Remote Address Swind Send-Q Rwind Recv-Q State –––––––––––––––––––– –––––––––––––––––––– ––––– –––––- ––––– –––––- ––––––––––- 10.88.88.140.8080 10.88.88.139.37259 1049792 0 1049800 0 FIN_WAIT_2
お客様
[root@kang ~]# netstat -f inet -P tcp -n TCP: IPv4 Local Address Remote Address Swind Send-Q Rwind Recv-Q State –––––––––––––––––––– –––––––––––––––––––– ––––– –––––- ––––– –––––- ––––––––––- 10.88.88.139.37259 10.88.88.140.8080 1049792 0 1049800 0 CLOSE_WAIT
それは理にかなっています:kudosはFINを
kang
送信しました。
FIN_WAIT_2
は、
kodos
が送信したFINに応答して
kang
からACKを受信したことを示し、
CLOSE_WAIT
は、
kang
がFINを受信したが応答にFINを送信しなかったことを示します。 これは完全に正常なTCP接続状態であり、永久に続く可能性があります。
kodos
が
kang
要求を送信し、他に何も送信する予定はなかったと想像して
kodos
。
kang
は何時間も楽しくデータを送り返すことができます。 私たちの場合にのみ、
kodos
実際にソケットを閉じました 。
少し待って、TCP接続の状態をもう一度確認しましょう。
kodos
接続が完全に失われますが、
kang
まだ存在することが
kodos
。
お客様
[root@kang ~]# netstat -f inet -P tcp -n TCP: IPv4 Local Address Remote Address Swind Send-Q Rwind Recv-Q State –––––––––––––––––––– –––––––––––––––––––– ––––– –––––- ––––– –––––- ––––––––––- 10.88.88.139.37259 10.88.88.140.8080 1049792 0 1049800 0 CLOSE_WAIT
アプリケーションがソケットを閉じ、スタックがFINを送信し、リモートスタックがFINを認識し、ローカルスタックが一定時間待機して接続を閉じると、TCPスタックに関連するあまり知られていない状況に直面しました。 理由は? リモート側がリブートされました。 このケースは、一方の接続がESTABLISHEDステータスにあり、もう一方の側がそれを認識していない場合に似ています。 唯一の違いは、アプリケーションがソケットを閉じたこと、および問題を処理できる他のコンポーネントがないことです。 その結果、TCPスタックは指定された期間待機し、接続を閉じます(相手側に何も送信しません)。
問題は後です。 この状況で
kang
が
kodos
データを送信すると
kodos
ますか?
kodos
側では既に接続が完了していますが、
kang
まだ接続が開いていると考えています。
お客様
2016-05-27T08:40:12Z: entering poll() kodos, are you there? 2016-05-27T08:41:34Z: poll returned events 0x1/0x0 2016-05-27T08:41:34Z: reading from stdin 2016-05-27T08:41:34Z: writing 22 bytes read from stdin to socket 2016-05-27T08:41:34Z: entering poll() 2016-05-27T08:41:34Z: poll returned events 0x0/0x10 2016-05-27T08:41:34Z: reading from socket dnc: read: Connection reset by peer
これは、パズル1で見たものと同じです:TCPスタックは接続が閉じられたことをまだ知らないため、
write()
成功します。 しかしRSTが来て、
poll()
あるスレッドを起動し、後続の
read()
要求がECONNRESETを返します。
結論:
- オペレーティングシステム、ネットワーク、またはハードウェアにエラーはありませんでしたが、両方の側が接続のステータスに同意しない可能性があります 。
- 上記の場合、
kang
kodos
がkang
からのデータをkodos
しているかどうか、またはkodos
ソケットを閉じてリッスンしていないかどうか(少なくともパケットを送信しない場合)を見つけることkang
できません。 したがって、通常の動作条件下では、そのようなセミオープン状態で長時間ソケットを使用するシステムを設計する価値はありません。
おわりに
TCPは通常、2つのシステム間の抽象化(「TCP接続」)をサポートするプロトコルとして提示されます。 一部のソフトウェアまたはネットワークの問題により、接続が切断されることがわかっています。 , , - . 例:
- , , , , .
- - , .
TCP. , TCP , . TCP, , . , , TCP- .
, , , , «TCP-, » — . - , , . , - ( keep-alive).
, «» TCP-. ( , ) , . , TCP- .
, :
- ( ) — , . . , — , .
- , TCP-. ,
read()
,write()
, . - , .
:
- ECONNRESET — ,
read()
,write()
. , RST. - ETIMEDOUT — ,
read()
,write()
. , , . , . , FIN KeepAlive.
, , - . , .