【TCPプロトコルとは】
TCP(Transimission Control Protocol)は、IPプロトコルの上位層に位置する
プロトコルで、UDPと同じ位置に属しますが、UDPと異なるのは、タイムアウト
と再送により高信頼なデータ転送を提供しているところです。
またUDPでは毎回相手のアドレスとポート番号を指定して送受信しますが、
TCPでは「コネクション確立シーケンス」で一度相手を特定すると、その後は、
「コネクション終了シーケンス」まで、コネクション確立シーケンスを省略して
データ転送だけで通信を行うことが出来ます。
このように仮想的なデータ通信路を確立してデータ転送を行うので、データの
紛失を検出することが可能になり高信頼なデータ転送を行うことが出来ます。
従ってTCPを使った時には、アプリケーション側で誤りチェック手順などをする
必要はありません。
さらに、このコネクションはポート番号を変えれば、同じ相手に対して複数の
コネクションを確立できるので、効率よいデータ伝送を行うことが可能になり
ます。
【TCPのフレームフォーマット】
まずTCPプロトコルで通信する場合のイーサネット上のフォーマットは
下図のようになっています。
この中で重要な働きをするのは、セッションフラグと呼ばれる6ビットの
データ部分です。このフラグでコネクションのコントロールをしています。
詳細は次項以下で説明します。
TCPヘッダ部のチェックサムはUDPと同じように仮想ヘッダを想定して
計算します。これで間違った相手と接続してしまうことを避けることができ
さらに信頼性があがります。
このチェックサムは、UDPでは計算しなくても良いようにも出来ますが
TCPでは必須となっています。
仮想ヘッダ部のデータ長は図のようにTCPヘッダを含めた長さで、フレーム
の中のヘッダ部に同じものはありませんので、フレーム全体長からイーサ
ネットヘッダとIPヘッダのサイズを引くという計算で求めます。
TCPのヘッダ長は4バイト単位でのバイト数で表します。オプションが無い時は
20バイトですので20÷4=5 となります。同様にオプションが4バイトの時は
6となります。
【TCPプロトコルの状態遷移】
TCPプロトコルではコネクションを確立して通信を行います。そのため
通信を開始、終了するためには手順が必要となっています。
この手順のコントロールは上記のセッションフラグで行います。
セッションフラグによるクライアント側と、サーバ側の状態は下図のような
遷移でコネクションをコントロールします。
下図は、1つのステーションがクライアントとサーバと両方になりうる場合の
遷移図です。
通常は太線の流れで遷移します。青の遷移がクライアント側で、PC側に
なります。 赤の太線がサーバ側、つまりPIC側の遷移になります。
細い線の遷移は通常で無い場合の遷移ですがありうる遷移です。
今回製作したTCP/IPスタックライブラリでは、サーバ機能のみとし、かつ
クライアントからの指示に従う受動的な動作のみに限定しましたので
赤い太線の遷移のみを組み込んでいます。
【TCPのセッションシーケンス】
上記の遷移図に従ってコネクションは下図のような流れで確立し、データ
送受信を行い、終了します。
この図はクライアント側が主導権を取っていて、コネクションの確立、終了
を始動しています。
またデータの送受信もクライアント側が主導し、クライアントのデータ送信への
応答の形でサーバからデータが返送される場合の手順です。
(クライアントがパソコンで、サーバがPICデバイスという前提です。)
《コネクション確立シーケンス》
(1) クライアント側からSYNフラグをOnにしたTCPパケットを送信します。
(2) サーバ側はSYNフラグを受信したら、SYNとACKのフラグをOnにし、
Ack番号を受信したSeq番号+1として返送します。
(3) クライアントからACKフラグをOnにし、Ack番号を受信したSeq番号+1
として返送すればコネクションが確立します。
ここで相手ポートと自ポートとの対応でソケットを作成し、バッファを
確保します。
この確立シーケンスを「3 Way HandShake」と呼んでいます。
《コネクション終了シーケンス》
(1) クライアント側が送受信が完了したら、FINフラグを送信します。
(2) サーバ側はFINフラグを受信したら、ACKとFINのフラグをOnにして
Ack番号を受信したSeq番号+1として返送します。
(3) クライアントはACKフラグをOnにし、Ack番号を受信したSeq番号+1
として送信すればコネクションが終了となります。
この中で両方のアプリケーションを終了とします。
クライアント側のパソコンは、一度コネクションが終了すると、数分間の間
は同じ相手の同じポート番号には接続できませんの注意が必要です。
《データ転送シーケンス》
(1) クライアント側から送信を開始します。(これはそう決めただけです)
データを準備してPSHフラグをOnにして送信します。
(2) サーバ側でPSHを受信したら、ACKを返すのですが、このとき送るべき
データがあるときは、データを一緒にしてPSHフラグとACKフラグの2つを
Onにして返送します。
このときAck番号には、受信したSeq番号+受信したデータ個数を入れて
返送します。
(3) クライアント側は、次のデータがあれば同じようにACKとPSHの両方をOn
にして送信します。
またAckg番号は同じように、受信したSeq番号+受信したデータ数 を
入れて送信します。
(4) サーバ側でこれ以上送信するデータが無い時は、ACKだけ返送します。
このときもAck番号には、受信したSeq番号+受信したデータ個数をセット
して返送します。
最後のデータがACKだけの時は、コネクション終了シーケンスを開始します。
【TCPのタイムアウトと再送】
TCPプロトコルではデータ転送の信頼性を確保するため、送信データにに対する
ACK返送の監視をしています。そして一定時間ACKが返って来ない場合には
送信を再度繰り返します。
一定回数再送してもACKが返って来ない場合には、RSTフラグを送信して
コネクションを強制終了させ、使用中のソケットを解放して初期状態とします。
監視時間と再送回数の決め方にはいろいろな方法があり、TCPの通信に
かかった往復時間をもとにして可変にすることが仕様になっています。
また輻輳を避けるためにタイムアウト時間を変えながら再送するようにも
なっています。
しかしここでは、簡単化のため、監視時間約3秒 繰返し回数3回 という
固定値とします。