シーケンス番号とACK

送信データはパケットに分割されて送出される。各パケットにはシーケンス番号と呼ばれるユニークな番号が割り当てられる。シーケンス番号はコネクション確立時にあるISN(シーケンス番号の初期値)が割り当てられ、コネクション確立中は送信ごとにこの値を更新しパケットに割りふる(パケットのseqフィールド)。毎回送信したbyte数をシーケンス番号に足し込むことにより、データストリームのどこまでを送受信したかを一意に判断することができる。*1

シーケンス番号123の送信パケットA(サイズは100byte)を送った後、次のパケットBを送る場合そのパケットB(サイズ20byte)のシーケンス番号は223(123+100)となる。更にその後のパケットC(サイズ50byte)のシーケンス番号は243(223+20)となる。

受信側でパケットAを受け取ったとき、受信側ではパケットAに対する応答(ACK)を返信し、確実に受け取ったことを保証する。

  1. 応答性が求められている場合、応答(ACK)情報のみパケットを即返信する。 パケットA(シーケンス番号123、サイズは100byte)に対する 返信の場合、返送パケットのACKフラグを立て、 ack_seqフィールドに223を設定する。(223以前のデータは確実に 受信したことを示す)
  2. 応答性が求められていない場合、応答(ACK)情報返信は一時的に保留する。 ACK情報のみのパケットは無駄にネットワーク資源を消費しないよう 通常はこの遅延ACKが用いられる。
    • 反対方向のデータ送信があればそのパケットにACK情報を相乗りさせる (piggybackと呼ばれる手法)。
    • ある一定時間が過ぎれば、応答(ACK)情報のみパケットを返信する。
    • 一定時間内にさらに複数のパケットを受信した場合、 応答(ACK)情報は一つに縮退させることができる。 もし、ACKを保留している間にパケットB(シーケンス番号223、サイズ20) を受け取った場合、次にACKパケットを作るときは ack_seqフィールドの値は243にすればよい。243以前のデータは確実に 受信したことを示すため、パケットAの受信もそこに含まれる。
  • もし、パケットBがロスト(または大きく遅延)し、パケットAとパケットCが 到着したときのことを考える。ACKパケットのack_seqフィールドには、 パケットA以前は確実に受け取ったことを示す値223を設定する。
    • パケットBが遅延して到着した場合、次のACKパケットのack_seq フィールドには、パケットCまで確実に受け取ったことを示す値293を 設定する。
    • もしパケットBが本当に失われたのであれば、いつまで経っても 戻って来ないACKに対し、送信側はパケットBとパケットCを再送する。 (パケットBだけでなくパケットCも送られるところに気を付けること。 TCPの拡張オプションでこのような時にパケットCを再送しなくても 済むような拡張がなさた)
img97.gif

通常は、送信するパケットのACKフラグは常にONにし、そのパケット送出時点で最も最新のACK情報を送り返し続ける。


(NIS)HirokazuTakahashi
2000年06月11日 (日) 22時29分57秒 JST
1


  1. *1後に説明するSYNパケットFINパケットはデータサイズ0であるが、論理的な1byteとして扱う。シーケンス番号を進めないと次に送るパケットと同じシーケンス番号を持つことになり、二つのパケットの区別を付けることができない。