第22話で戻ってきた小さなACKが、イトの手の中で光っていた。
タブレットからaccess pointまで、一つのWi-Fi frameが届いた印だ。
イトはその光を、ルーターの向こうにある遠隔到着slotへ運んだ。
「これを入れれば、届いたことにできる」
slotへ重ねようとした瞬間、奥のnetworkで一つの青い箱が消えた。
遠隔の動画service gateは、暗いままだった。
イト
ACKは戻った。なのに、向こうには届いていない?
ユイ
そのACKは、どこから戻ってきたものでしたか
イト
すぐ近くのaccess point……。遠くのserviceからじゃない
イトは、ACKをslotへ入れる手を止めた。
ラボの壁に、最後の字幕一行が現れる。
その一行を表すbyte streamは、青いbeadの列として可視化されていた。
beadの数や区切りはこの実験の表示で、文字数とbyte数の一般則ではない。
beadは三つのかたまりに分かれ、それぞれ別のIP datagramへ入る。
遠隔側で全beadが順番どおりそろわなければ、字幕gateは開かない。
上には、残り十二秒の輪。
これも、このラボだけの訓練時間だ。
localのreceiptを、遠隔へ貼れる?
最初のIP datagramが、routerを二つ越えた。
二番目は、途中の暗い区間へ入ったまま出てこない。
三番目だけが、先に遠隔hostへ着いた。
受信台には、最初のbead群と最後のbead群が並ぶ。
中央が空いていた。
マコト
近いWi-Fi hopでは受け取れても、その先のIP datagramは別の場所で失われることがある
ピコ
一つのreceiptで、通っていない区間まで確認したことにはできないんだ
イト
じゃあ、どの約束をどこに置けばいい?
TCP/IPという名前は、一枚の万能な保証書ではない。
この実験台には、役割の違う層が重なっている。
- applicationは、字幕という意味を扱う
- TCPは、endpoint間でbyte streamの届け方を扱う
- IPは、source hostからdestination hostへdatagramを運ぶ
- Wi-Fiは、今回のlocal linkでframeを渡す
下の層で受け取ったことと、上の層の目的が終わったことは、同じではない。
字幕gateの輪は、残り九秒になった。
誰に、覚えてもらう?
操作台に、三枚の設計cardが開いた。
- local Wi-Fi ACKを遠隔到着slotへ入れ、全beadが届いたことにする
- 通過するすべてのrouterへ、三datagramの順番と再送を最後まで覚えさせる
- routerはIP datagramを一つずつforwardし、信頼性が必要な今回の通信では両endpointにTCPの台帳を置く
一番目なら、一秒でgateを開けられる。
けれど、中央の空白は消えない。
二番目なら、途中のrouterが全部を見張ってくれそうだ。
けれど、経路が変わったらどうなるのだろう。すべてのrouterが、この字幕streamの状態を最後まで抱えるのだろうか。
イトは、最初に手の中のACKを見た。
それを遠隔slotではなく、tabletとaccess pointの間にあるlocal hopのhookへ戻した。
次に、routerの上へ置かれた「全streamを記憶する台帳」を外す。
最後に、source hostとdestination hostの二か所だけへ、同じ形のTCP ledgerを置いた。
イト
routerには、次へ運ぶIPの仕事をしてもらう。順番と欠けは、通信の両端で見る
ユイ
途中の道が変わっても、両端なら同じstreamを見続けられます
ピコ
その選択なら、TCPの役割を動かせるよ
ピコは台帳を置かなかった。
local receiptを戻し、routerの余計な台帳を外し、二つのendpointを選んだのはイトだった。
IPは運ぶ。でも、そろうとは約束しない
source側のapplicationが、beadの列をTCPへ渡した。
この学習レーンでは、TCPがbyte streamの位置を記録し、三つのsegmentとして送り出す。
各segmentはIP datagramに入ってnetworkへ進んだ。
IP headerにはsourceとdestinationのaddressがある。
途中のrouterはdestinationを手掛かりに、datagramごとに次のhopを選ぶ。
ただしIPは、三つが全部届くこと、同じ順で着くこと、重複しないことをend-to-endで保証しない。
今回も、一番目と三番目は着き、二番目は着かなかった。
これは「IPが壊れた」のではない。
lossやreorderingが起こりうるnetworkの上で、必要なreliabilityを上の層へ置く設計だ。
IETFのRFC 1122は、IPをend-to-end delivery guaranteeのないconnectionless / datagram serviceとして説明し、必要なreliabilityをhostのtransport layerまたはapplicationへ置くInternet architectureを示している。
現実のnetworkにはstatefulなmiddleboxもある。それでも、この話では「各routerがTCP connection全体のreliabilityを代行する」とは考えない。
TCPは、空白を見逃さなかった
destination側のTCP ledgerには、最初と最後の位置が光っていた。
真ん中だけが空白だ。
三番目のsegmentは着いている。
でも、その中の後ろのbytesを、先にapplicationへ渡して字幕を欠けたまま完成させない。
TCPは、sequence numberを使ってbyte streamの位置を追う。
senderはACKの進み方やtimerなどからlossを検出し、足りないdataをretransmitする。どのACKでどう判断するかは、第25話で詳しく見る。
残り六秒。
source側のTCP ledgerで、中央のsegmentがもう一度光った。
イトは、そのsegmentを再送slotへ入れた。
同じ欠けを埋めるIP datagramが、新しい一歩を走り出す。
途中のrouterは、最初の失敗を覚えて道を保証したわけではない。
目の前のdatagramを、一つずつ次へforwardする。
missing segmentがdestination側へ届いた。
空白へ、中央のbead群が収まる。
stream全体が、先頭から切れ目なく青く光った。
destination側TCPのACKがsource endpointへ戻る。
そのあとで、そろったbyte streamがapplication slotへ渡された。
字幕gateが開き、最後の一行が壁へ映った。
輪は、一つを残して止まった。

この一件で、成功したのは今回の字幕streamだ。
どんな通信でも十二秒以内にそろう、三segmentに等分される、という意味ではない。
TCPのACKなら、applicationも終わった?
イトはdestination側から戻ったTCP ACKを、今度こそ「全部完了」のslotへ置こうとした。
しかし、remote hostには二つのlampがある。
一つは、TCPがbytesを受け取ったlamp。
もう一つは、applicationがそのbytesを読み、字幕として扱ったlamp。
TCP lampが先に点き、少しあとでapplication lampが点いた。
イト
TCP ACKも、相手のapplicationが意味を理解して保存した証明ではないんだ
マコト
transportの受信と、applicationの処理結果は分けて考える必要があるね
ユイ
必要ならapplication自身のresponseで、その先を確認します
TCPはapplicationへ、reliable, in-order byte-stream serviceを提供する。
IETFの現行TCP標準RFC 9293は、TCPがsequence numberでpacket lossを検出し、retransmissionで補正することを含め、このserviceを定めている。
でもTCPは、字幕の意味や予約の成立、dataの保存完了まで理解しない。
層を分けるとは、責任を曖昧にすることではない。
どのreceiptが、どこまでを見たのかを狭く正確にすることだった。
関連ガイド「TCP/IPとは?」では、application / transport / internet / linkの重なりを、物語から離れて一覧で確認できる。
そろうまで待つ代償
完成した字幕の横で、別の音声streamが流れ始めた。
話し手の声は、もう次の音へ進んでいる。
ところが、途中で遅れた古い一片が、あとから到着した。
字幕では、欠けたbytesを待って順番どおりにすることに価値があった。
live音声では、古い一片を待つ間に「いま」の声が遅れるかもしれない。
TCPには、connection state、ACK、retransmission、順番待ちのcostがある。
それは無駄ではない。
必要なreliabilityを買うためのcostだ。
けれど、すべてのapplicationが同じ買い方をする必要はない。
イト
欠けたら困る字幕では待った。でも、古い声を待つのが正解とは限らない
ピコ
次は、同じdata lossを前にTCPとUDPのどちらを選ぶか比べよう
次回:失った一片を、待つ? 待たない?
左の字幕台では、streamのbeadが順番どおりに光っている。
右のlive音声台では、新しい波の後ろから、遅れた古いbeadが転がってきた。
イトの前に、二つのtransport cardが開く。
一枚は、欠けを補い、順番をそろえる。
もう一枚は、必要最小限のdatagram serviceをapplicationへ渡す。
同じ「速く届けたい」でも、失って困るものは違う。
次回、ピコルート第24話。
TCPとUDPは、どちらが速いかではなく、何を誰が引き受けるかで選ぶ。

