TCP は受け取り側の返事で、落ちた塊に気づいて送り直す。UDP は返事を待たないので、落ちた塊は黙って消える。速い遅いではなく、何を諦めるかの違い TCP は返事で気づいて送り直し、UDP は投げたら終わり 混んだ中継機は、あふれた塊を黙って捨てる。捨てたことは、送り主に知らされない (簡略図) TCP (受取印を返す書留) 受け取り側が「ここまで受け取った」と返す 送り主 中継機 受け取り側 塊 1 返事「1 まで受け取った」 塊 2 捨てられる 返事が来ないので、 塊 2 を送り直す 返事「2 まで受け取った」 返事が来ない塊に気づき、送り直す UDP (返事なしの葉書) 投げたら終わり。返事も送り直しもない 送り主 中継機 受け取り側 塊 1 塊 2 捨てられる 塊 3 返事は来ない。 塊 2 は送り直されない 落ちた塊 2 は、送り主に知らされず消える どちらを選ぶかの目安 作るもの 乗るもの Web サービス、API TCP。意識せずとも TCP に乗る 通話、配信、対戦ゲーム UDP。落ちた分の後始末はアプリ側 守りたいものが到達なら TCP、いまこの瞬間なら UDP TCP は受け取り側の返事で、落ちた塊に気づいて送り直す。 UDP は返事を待たないので、落ちた塊は黙って消える。速い遅いではなく、 何を諦めるかの違い
TCP は受け取り側の返事で、落ちた塊に気づいて送り直す。UDP は返事を待たないので、落ちた塊は黙って消える。速い遅いではなく、何を諦めるかの違い TCP は返事で気づいて送り直し、 UDP は投げたら終わり 混んだ中継機は、あふれた塊を黙って捨てる。 捨てたことは、送り主に知らされない (簡略図) TCP (受取印を返す書留) 受け取り側が「ここまで受け取った」と返す 送り主 中継機 受け取り側 塊 1 返事「1 まで受け取った」 塊 2 捨てられる 返事が来ないので、塊 2 を送り直す 返事「2 まで受け取った」 返事が来ない塊に気づき、送り直す UDP (返事なしの葉書) 投げたら終わり。返事も送り直しもない 送り主 中継機 受け取り側 塊 1 塊 2 捨てられる 塊 3 返事は来ない。 塊 2 は送り直されない 落ちた塊 2 は、送り主に知らされず消える どちらを選ぶかの目安 作るもの 乗るもの Web サービス、API TCP。 意識せずとも TCP に乗る 通話、配信、対戦ゲーム UDP。落ちた分の後始末は アプリ側 守りたいものが到達なら TCP、 いまこの瞬間なら UDP TCP は受け取り側の返事で、 落ちた塊に気づいて送り直す。 UDP は返事を待たないので、 落ちた塊は黙って消える。速い遅いではなく、 何を諦めるかの違い
届かなかったことに、送った側は気づけない
ネットワーク にデータを流しても、途中で捨てられることがあります。混雑した中継機は、あふれた分を黙って捨てるからです。
捨てられても、また送ればいいだけなんだから、そんなに困らなくない?
困るのは、捨てられたことが送り主に知らされない点です。何も言われないので、送り主は届いたと思い込んだままになります。この不安を引き受けてくれるのが TCP 、引き受けないのが UDP です。どちらも同じ段で使える、並んだ選択肢です。
どちらを使うかはアプリを書くときに選びます。選んだ結果はコードの見た目にほとんど現れませんが、うまくいかなかったときの挙動がまるで変わります。
確実に届けるために、TCP が 肩代わりしていること
TCP は「届くものは順番どおりに届く。落ちた分は送り直す」を約束します。ただし、回線が切れたり時間切れになったりして、送り直しても届かないときは、エラーとして知らされます。約束を守るために、内部で次のことをしています。
送る前に相手と挨拶を交わし、両方向で話が通じることを確かめる
送る塊 1 つ 1 つ に通し番号を振り、受け取り側で順番に並べ直す
受け取り側に「ここまで受け取った」 と返事をさせ、返事が来ない分を送り直す
混雑を検知したら、送る速度を自分から落とす
書く側は、この仕組みを一切意識しません。届く間は順番も守られる、という前提でコードを書けます。ただし、接続が切れた、時間切れになった、といったエラーへの備えは、アプリ側に残ります。Web の 通信がそのまま TCP に 乗っているのも、面倒を全部下に押し付けられるからです。
見落としやすいのは、これらが全部、送り主と受け取り側の 2 者だけで完結している点です。途中の中継機は何も手伝いません。混んでいると教えてもくれないし、落とした分を覚えてもいません。両端だけで辻褄を合わせる設計だからこそ、回線や中継機が違っても、同じ仕組みをそのまま使えます。
じゃあ途中の中継機を全部賢くすれば、TCP なんて要らなくなるんじゃないの?
いや、中継機が賢くなっても TCP は 要らなくならぬ。届いたかを最後に確かめられるのは、受け取った本人である両端だけじゃ。だから回線や中継機が違っても、両端で確認と送り直しをする同じ仕組みを使えるのじゃ。
約束しないほうが速い場面がある
TCP は順番を守るため、欠けた塊の送り直しが届くまで、後ろの塊は届いていても渡さない。通話や対戦では、この待ちがそのまま遅れになる TCP は欠けた 1 つを待つ間、後ろの塊も止める 通し番号 1 から 5 の塊のうち、2 が途中で捨てられたとき TCP は番号順にしか渡さない 上のアプリへは、通し番号の順に渡す 受け取り側に届いた塊 1 2 3 4 5 届いているのに、 待たされる アプリに渡した分 1 だけ渡す 1 2 の送り直しが届くまで、アプリは 3 から先を使えない。通話や対戦では、この待ちがそのまま遅れになる UDP は届いた順に渡す 落ちた 2 は送り直さない 受け取り側に届いた塊 1 2 3 4 5 2 は諦める アプリに渡した分 届いた分を渡す 1 3 4 5 アプリは 3, 4, 5 を先に使える。欠けた 2 の後始末は、アプリ側の仕事 守りたいもので選ぶ 方式 守るものと場面 TCP 到達と順番を守る。Web サービスや API UDP いまこの瞬間を守る。通話、配信、対戦ゲーム TCP は順番を守るため、欠けた塊の送り直しが届くまで、 後ろの塊は届いていても渡さない。通話や対戦では、この待ちがそのまま遅れになる
TCP は順番を守るため、欠けた塊の送り直しが届くまで、後ろの塊は届いていても渡さない。通話や対戦では、この待ちがそのまま遅れになる TCP は欠けた 1 つを待つ間、 後ろの塊も止める 通し番号 1 から 5 の塊のうち、 2 が途中で捨てられたとき TCP は番号順にしか渡さない 上のアプリへは、通し番号の順に渡す 受け取り側に届いた塊 1 2 3 4 5 届いているのに、待たされる 1 だけ渡す アプリに渡した分 1 2 の送り直しが届くまで、アプリは 3 から先を使えない。 通話や対戦では、この待ちがそのまま遅れになる UDP は届いた順に渡す 落ちた 2 は送り直さない 受け取り側に届いた塊 1 2 3 4 5 2 は諦める 届いた分を渡す アプリに渡した分 1 3 4 5 アプリは 3, 4, 5 を先に使える。欠けた 2 の後始末は、 アプリ側の仕事 守りたいもので選ぶ 方式 守るものと場面 TCP 到達と順番を守る。Web サービスや API UDP いまこの瞬間を守る。通話、配信、対戦ゲーム TCP は順番を守るため、 欠けた塊の送り直しが届くまで、 後ろの塊は届いていても渡さない。 通話や対戦では、この待ちがそのまま遅れになる
UDP は 逆です。挨拶をせず、通し番号を振らず、返事も待たず、送り直しもしません。宛先を書いて投げたら終わりです。
一見すると劣化版ですが、そうではありません。 TCP は順番を守るために、後ろの塊が先に届いていても、前の塊が届くまで上のアプリへ渡さずに待たせます。通話や対戦ゲームでは、この待ち時間そのものが致命傷になります。1 コマ落ちた過去を取り戻すより、いまの音と映像を先に進めたい。そういう場面では、諦める設計のほうが体感がはっきり良くなります。
「速い遅い」 の差ではなく、「何を諦めるか」 の差だと捉えてください。守りたいものが到達なら TCP、いまこの瞬間なら UDP です。そして UDP を 選んだ場合、落ちた分の後始末はアプリ側の仕事になります。何もしなくていいわけではありません。
実際の選び方はほぼ決まっています。作るものが Web サービスや API なら、意識せずとも TCP に 乗ります。UDP を 自分で選ぶのは、通話や配信、対戦ゲームのように待ち時間が致命的な場面か、既存のやり方では遅すぎると実測で分かったときです。まず TCP、理由があるときだけ UDP、という順番で考えてください。
つまり、基本は TCP で 、UDP は 理由がはっきりあるときだけ選ぶってことか
うむ、その順番で考えるのが実務的じゃ。ただし、実測でどこまで遅いと判断するかまでは、この回では扱っていない。