[高度なネットワーク] Posix API とネットワーク プロトコル スタック (4)

1. UDPデータフレーム

ユーザー データグラム プロトコル (UDP) は、トランスポート層で単純で信頼性の低いデータグラム送信サービスを提供するコネクションレス型ネットワーク プロトコルです。UDP にはタイムアウト再送信、アウトオブオーダー データ処理、輻輳制御などの複雑な機能がないため、TCP と比較して遅延とオーバーヘッドが低くなります。このため、UDP は、リアルタイム アプリケーション (VoIP、ゲームなど) や単純なクエリ アプリケーション (DNS など) にとって最初の選択肢となります。

UDP データ フレームの構造は比較的単純で、次の部分が含まれています。

  • 送信元ポート: これは、UDP データグラムを送信するアプリケーションのポートを識別するオプションのフィールドです。
  • 宛先ポート: このフィールドは、UDP データグラムを受信するアプリケーションのポートを識別するために使用されます。
  • 長さ: このフィールドは、UDP ヘッダーとデータの合計の長さを定義します。
  • チェックサム: これは、ヘッダーとデータのエラーをチェックするために使用されるオプションのフィールドです。

もちろん、UDP データ フレームの作成と送信のプロセス全体をできるだけ明確に説明するために、説明を再度述べます。

1.1 ネットワークプロトコルスタックにおけるUDPデータフレームの送信プロセス

アプリケーションがデータのコピーを別のマシン上のアプリケーションに送信したいとします。このプロセスは次のステップに分かれています。

  1. アプリケーション層: 送信側のアプリケーションはデータを準備し、送信に UDP プロトコルを使用することを決定します。このデータは生データまたはペイロードと呼ばれます。

  2. トランスポート層: アプリケーション層は、データをトランスポート層の UDP プロトコルに配信します。UDP プロトコルは、送信元ポートと宛先ポート、長さおよびチェックサム フィールドを含む UDP ヘッダーを追加します。このプロセスにより、UDP データグラムが形成されます。

  3. ネットワーク層: トランスポート層の UDP プロトコルは、UDP データグラムをネットワーク層の IP プロトコルに配信します。IP プロトコルは、送信元 IP アドレスと宛先 IP アドレスを含む IP ヘッダーを追加します。このプロセスにより、UDP データグラムを含む IP データグラムが形成されます。

  4. リンク層: ネットワーク層は IP データグラムをリンク層に渡します。リンク層は、IP データグラムの前後にリンク層のヘッダーとトレーラーを追加してデータ フレームを形成します。このデータ フレームは、物理媒体 (イーサネット、ワイヤレス ネットワークなど) を介して送信されます。

データ フレームが受信側マシンに到達すると、プロセスは逆に行われます。

  1. リンク層: 受信側のリンク層は、物理媒体からデータ フレームを受信し、ヘッダーとトレーラーを削除して、IP データグラムをネットワーク層に渡します。

  2. ネットワーク層: ネットワーク層は IP データグラムを受信し、IP ヘッダーを削除して、UDP データグラムをトランスポート層に渡します。

  3. トランスポート層: トランスポート層は UDP データグラムを受信し、UDP ヘッダーを削除して、元のデータまたはペイロードをアプリケーション層に渡します。

  4. アプリケーション層: 最後に、アプリケーション層は元のデータを受け取り、後続の処理を実行します。

以上がネットワークプロトコルスタックにおけるUDPデータフレームの送信処理です。送信プロセス中に、元のデータが層ごとにデータ フレームにカプセル化され、受信側で層ごとに取り除かれることがわかります。各層は独自のヘッダ情報をデータに追加して、それぞれの機能を実現します。UDP の役割は、トランスポート層でエンドツーエンドのデータ送信サービスを提供することです。

1.2 UDPデータフレームの特徴

  1. コネクションレス: UDP はコネクションレス プロトコルです。つまり、データを送信する前に接続を確立する必要がありません。このため、UDP は、DNS クエリやビデオ ストリーミングなどの 1 回限りのデータ転送に特に適しています。

  2. 信頼性の低さ: UDP は信頼性の低いプロトコルであり、データ フレームが宛先に正常に到達することを保証しません。ネットワークが混雑している場合、UDP データ フレームがドロップされる可能性があります。さらに、UDP は、データ フレームが間違った順序で到着した場合でも並べ替えません。

  3. リアルタイム アプリケーションに最適: UDP は確認応答情報、再送信メカニズム、複雑なリンク確立プロセスを必要としないため、遅延が非常に低くなります。このため、UDP は、VoIP 通話、オンライン ゲームなどのリアルタイム アプリケーションにおいて非常に価値があります。これらのアプリケーションでは、ある程度のデータ損失が発生する可能性がありますが、遅延の増加はユーザー エクスペリエンスに大きな影響を与えます。

  4. ブロードキャストとマルチキャストのサポート: UDP はブロードキャストとマルチキャストをサポートします。ブロードキャストでは UDP データ フレームをネットワーク上のすべてのホストに送信でき、マルチキャストではデータ フレームを特定のホスト グループに送信できます。このため、UDP は、ネットワーク上でのライブ ビデオのストリーミングなど、ネットワーク上での情報配信に最適です。

2. イーサネットプロトコルヘッダー

イーサネット プロトコル ヘッダーはデータ リンク層の一部であり、イーサネット フレームの送信元アドレスと宛先アドレスを指定し、フレーム タイプを定義するために使用されます。

2.1 イーサネットプロトコルヘッダーの主要コンポーネント

  1. 宛先アドレス: このフィールドは、宛先イーサネット インターフェイスの物理アドレスを含む 6 バイトのフィールドです。マシンがデータ フレームを送信したい場合は、宛先マシンのイーサネット アドレスをこのフィールドに書き込みます。

  2. 送信元アドレス: このフィールドも 6 バイトで、送信側マシンのイーサネット インターフェイスの物理アドレスが含まれます。このようにして、受信側はデータ フレームがどこから来たのかを知ることができます。

  3. タイプ/長さ: これは 2 バイトのフィールドです。このフィールドの値が 1536 (0x0600) 以上の場合はイーサネット フレームのタイプを表し、このフィールドの値が 1500 以下の場合はイーサネット フレームの長さを表します。type フィールドは、IPv4 や IPv6 などの上位層プロトコルのタイプを識別するために使用されます。

  4. 仮想 LAN タグ (VLAN タグ、オプション) : これは、優先コード ポイント (PCP)、フレーム識別プロトコル識別子 (ドロップ適格インジケータ、DEI)、および仮想 LAN 識別子 (VLAN 識別子、VID) を含むオプションの 4 バイトのフィールドです。このフィールドはすべてのイーサネット フレームに存在するわけではなく、802.1Q VLAN タグが存在する場合にのみ表示されます。

上記のフィールドは、イーサネット フレームのヘッダーを説明することに注意してください。実際のイーサネット フレームには、データ部分とフレーム チェック シーケンス (FCS) フィールドも含まれます。FCS フィールドは、イーサネット フレームの完全性をチェックするために使用されます。データ送信中にエラーが発生したかどうか。

イーサネット フレーム ヘッダーの設計により、ネットワーク機器はデータ フレームを正しい宛先に正確に送信できるようになり、データの完全性が確実に保証されます。実際のネットワーク環境では、イーサネット プロトコルは現在最も広く使用されている LAN テクノロジーの 1 つであり、その設計思想や技術的詳細については、当社が深く研究し理解する価値があります。

2.2 イーサネットプロトコルの設計思想と技術的詳細

  1. シンプルさ: イーサネットの設計哲学の 1 つは、シンプルさを保つことです。たとえば、イーサネットはブロードキャストベースのプロトコルであり、すべてのノードが同じブロードキャスト ドメイン内にあります。これは、各ノードがすべてのデータ フレームを受信し、イーサネット フレーム ヘッダーの宛先アドレスに基づいてデータ フレームを処理するかどうかを決定することを意味します。

  2. コネクションレス: イーサネットはコネクションレスです。つまり、データ フレームを送信するノードは、データを送信する前に受信ノードとの接続を確立する必要がありません。このコネクションレスの性質により、イーサネットはよりシンプルかつ効率的になりますが、同時にイーサネット自体が信頼性を保証しないことも意味します。

  3. メディア アクセス制御 (MAC) : イーサネットはメディア アクセス制御方式として CSMA/CD (キャリア センス多重アクセス/衝突検出) を使用します。イーサネット ノードがデータを送信する必要がある場合、最初にメディア (通常はケーブル) をリッスンして、他のノードがデータを送信しているかどうかを検出します。そうでない場合は、データの送信を開始します。2 つのノードが同時にデータの送信を開始すると競合が発生し、このときノードは送信を停止し、ランダムな時間待機してから再度送信を試みます。

  4. フレーム構造: イーサネット フレームの構造設計はシンプルかつ効率的で、宛先アドレス、送信元アドレス、タイプ/長さ、データ ロードなどのフィールドが含まれます。さらに、エラー検出用のフレーム チェック シーケンス フィールドがあります。このフレーム構造は、データ伝送の基本的なニーズを満たすだけでなく、全体的なシンプルさも保証します。

  5. スケーラビリティ: イーサネットは、高度にスケーラブルになるように設計されています。たとえば、元のイーサネットは 10 Mbps の伝送速度しかサポートしていませんでしたが、テクノロジーの進歩により、イーサネットは 100 Mbps、1 Gbps、さらには 10 Gbps を超える速度をサポートできるようになりました。さらに、イーサネットは、ツイストペア、光ファイバー、電波などのさまざまな物理メディアをサポートします。

上記は、イーサネット プロトコルの設計思想と技術的詳細の一部です。全体として、イーサネットの設計はシンプルさ、接続性、拡張性を重視しており、さまざまなネットワーク環境で広く使用できるようにしています。

3. IPプロトコル

3.1 IPプロトコルの機能と特徴

インターネット プロトコル (IP) は、インターネット プロトコル スイート (TCP/IP) のコア プロトコルであり、IP データグラムにカプセル化されたデータを送信元ホストから宛先ホストに送信する役割を果たします。その中核機能には、アドレスの識別、断片化と再構成、ルーティングとエラー処理などが含まれます。

  • アドレス識別: IP アドレスはネットワーク内のデバイスの一意の識別子であり、これによりデータグラムを送信元ホストから宛先ホストに正確にルーティングできます。IP アドレスは、IPv4 (32 ビット) と IPv6 (128 ビット) の 2 つの形式に分けられます。

  • フラグメンテーションと再アセンブリ: IP プロトコルは、転送のために大きなデータグラムを小さなデータグラムに分解し、受信側でこれらのデータグラムを再組み立てして、さまざまなネットワークに適応できるフラグメンテーションと再アセンブリのメカニズムを提供します。環境内の最大伝送ユニット (MTU) の制限。

  • ルーティング: IP プロトコルの主要な機能はルーティングです。ルーティングは、ルーティング テーブル内の情報に基づいて、送信元アドレスから宛先アドレスまでのデータグラムの最適なパスを選択します。

  • エラー処理: IP プロトコルには、データグラムの送信中に発生するエラーを処理する機能がありますが、エラーの回復は行いません。データグラムの送信中にエラーが発生した場合、IP は ICMP メッセージを生成して送信者に通知しますが、エラーのあるデータグラムを再送信するタスクは通常、上位層プロトコル (TCP など) の責任です。

上記のコア機能に加えて、IP プロトコルにはいくつかの追加の機能があります。たとえば、IP プロトコルはコネクションレス型です。これは、データグラムを送信するホストが送信前に受信ホストとの接続を確立する必要がないことを意味します。また、IP プロトコルもベストエフォート型であり、データグラム伝送の信頼性の保証、エラー回復、フロー制御や輻輳制御は行わず、これらのタスクは上位層のプロトコルに引き渡されます。 TCPとして。

3.2 IPプロトコルヘッダー

IP プロトコル ヘッダーには、データグラムの送信に必要なすべての重要な情報が含まれています。IPv4 では、プロトコル ヘッダーの長さは 20 バイトに固定されています (オプション フィールドが使用されない場合)。一方、IPv6 では、ヘッダーの長さは 40 バイトに固定されています。プロトコル ヘッダーの主なフィールドは次のとおりです。

  • バージョン: IP プロトコルのバージョン (IPv4 または IPv6) を示します。

  • ヘッダ長: IP ヘッダの長さを示します。

  • サービス タイプ/トラフィック レベル: IPv4 では、このフィールドはサービス タイプと呼ばれ、データグラムの優先順位と QoS 要件を示すために使用されます。IPv6 では、このフィールドはトラフィック クラス (Traffic Class) とフロー ラベル (フローレーベル)2部構成。

  • 全長:全体を指します

データグラムの長さ (ヘッダーとデータを含む)。

  • Time to Live/Hop Limit : IPv4 では、このフィールドは Time to Live (TTL) と呼ばれ、ネットワーク内のデータグラムの生存時間を制限するために使用されますが、IPv6 では、このフィールドは Hop Limit (ホップ リミット) と呼ばれます。 )。

  • プロトコル/次のヘッダー: IPv4 では、このフィールドはプロトコルと呼ばれ、上位層プロトコルのタイプを示すために使用されます。IPv6 では、このフィールドは次のヘッダーと呼ばれます。

  • ヘッダーチェックサム: 送信中にヘッダーにエラーがあるかどうかをチェックするために使用されます。

  • 送信元アドレスと宛先アドレス: データグラムの送信ホストと受信ホストの IP アドレスをそれぞれ示します。

3.3 IP プロトコルのオプションと拡張機能

IP プロトコルは、より多くの機能をサポートするためのいくつかのオプションと拡張機能を提供します。IPv4 では、これらのオプションには、ソース ルーティング オプション、レコード ルーティング オプション、タイムスタンプ オプションなどが含まれますが、これらに限定されません。ただし、これらのオプションはプロトコルの複雑さを増し、セキュリティ上の問題を引き起こす可能性があるため、実際にはあまり使用されません。

IPv6 では、ヘッダーを簡素化し、処理速度を向上させるために、ほとんどのオプションが基本ヘッダーの外に移動され、拡張ヘッダーに配置されました。IPv6 では、ホップバイホップ オプション、ルーティング、フラグメント、認証、セキュリティ ペイロードのカプセル化など、さまざまな拡張ヘッダーが定義されています。

4. UDPプロトコル

ユーザー データグラム プロトコル (UDP) は、コネクションレスでベストエフォートのデータ送信サービスを提供する、シンプルなデータグラム指向のトランスポート層プロトコルです。以下は、UDP プロトコルの詳細な紹介です。

4.1 UDPプロトコルの機能と特徴

UDP プロトコルの主な機能は、シンプルで高速なデータ送信サービスを提供することです。UDP プロトコルはデータの信頼性、順序、またはデータの整合性をまったく保証しませんが、まさにこのシンプルさゆえに、UDP は多くのアプリケーション シナリオで利点を持っています。たとえば、VoIP (音声通話)、ビデオ会議、オンライン ゲームなど、高いリアルタイム要件があり、ある程度のパケット損失を許容できる一部のアプリケーションでは、UDP が推奨されます。

一方、UDP プロトコルはコネクションレス型であり、データの送受信の間に接続の確立と切断のプロセスがなく、いつでもデータを送信できるため、一部のリクエスト/レスポンス モードのサービスに適しています。 DNS クエリなど、非常に便利です。

UDP プロトコルは、1 対 1、1 対多、多対 1、および多対多の対話型通信モードもサポートします。

4.2 UDP データグラム

UDP データグラムはヘッダーとデータの 2 つの部分で構成され、ヘッダーの長さは 8 バイト固定です。ヘッダーには次のフィールドが含まれます。

  • 送信元ポートと宛先ポート: データグラムの送信側と受信側のポート番号をそれぞれ示します。ポート番号は、ホスト上のさまざまなアプリケーションを区別するために使用されます。

  • 長さ: UDP データグラム全体 (ヘッダーとデータを含む) の長さを示します。

  • チェックサム: 送信中にデータグラムにエラーがあるかどうかをチェックするために使用されます。これはオプションのフィールドですが、実際には一般的に使用されます。

4.3 UDP プロトコルと IP プロトコルの関係

UDP プロトコルはトランスポート層で動作し、ネットワーク層の IP プロトコルに依存してデータグラムの送受信を完了します。UDP プロトコルはアプリケーション層のデータをデータグラムにカプセル化し、UDP ヘッダーを追加した後、データグラムは IP プロトコルに渡されます。IP プロトコルは、UDP データグラムの宛先 IP アドレスとルーティング テーブルに基づいて、データグラムをターゲット ホストに送信します。ターゲット ホストがデータグラムを受信した後、IP プロトコルはデータグラムを UDP プロトコルに渡し、UDP プロトコルはヘッダーを削除してデータをアプリケーション層に渡します。

5. UDPプロトコルの概要

インターネットでは、データ伝送には複数のネットワーク レベルが関係します。各層には独自の責任と特性があり、連携してデータの送受信をサポートします。このプロセスでは、MAC アドレス、IP アドレス、ポート番号がすべて重要な役割を果たします。

5.1 MAC アドレス

MAC アドレスはデータ リンク層 (イーサネット層) で使用され、ネットワーク インターフェイス コントローラー (ネットワーク インターフェイス カード、NIC とも呼ばれます) の一意の識別子です。イーサネットでは、データはフレームの形式で送受信されます。フレームのヘッダーには送信元 MAC アドレスと宛先 MAC アドレスが含まれています。これにより、フレームが送信元ホストから宛先ホストに正しく送信されることが保証されます。

5.2 IPアドレス

IP アドレスはネットワーク層で使用され、ネットワーク内のホストの一意の識別子です。データグラムを送信元ホストから宛先ホストに送信する必要がある場合、宛先ホストの IP アドレスに基づいてルーティング パスが決定されます。IP データグラムのヘッダーには、正しいルーティング パスに従ってデータグラムがターゲット ホストに送信されることを保証するために、送信元 IP アドレスと宛先 IP アドレスが含まれています。

5.3 ポート番号

ポート番号は、ホスト上の特定のアプリケーションを識別するためにトランスポート層 (TCP または UDP) で使用されます。ネットワーク サービスを同時に使用するホスト上に複数のアプリケーションが存在する可能性があるため、これらのアプリケーションを区別するにはポート番号が必要です。TCP または UDP データグラムのヘッダーには、データが正しいアプリケーションに送信されることを保証するために、送信元ポート番号と宛先ポート番号が含まれています。

5.4 UDPプロトコルの概要

上記の内容を検討すると、UDP プロトコルはトランスポート層プロトコルとして機能し、その役割はアプリケーション間のデータ送信サービスを提供することであることがわかります。UDP プロトコルはコネクションレスであり、ベストエフォート型のサービスを提供します。つまり、データの信頼性、順序、整合性は保証されません。ただし、このシンプルさゆえに、UDP プロトコルは VoIP、ビデオ会議、オンライン ゲームなどの多くのシナリオで利点を発揮します。一方、UDP プロトコルは、その動作を完了するためにネットワーク層の IP プロトコルとデータリンク層のイーサネット プロトコルにも依存します。一般に、UDP プロトコルはインターネット プロトコル スタックの重要な部分であり、その機能は比較的単純ですが、ネットワーク通信において重要な役割を果たします。

6. UDPの場合

以下は、クライアント側コードとサーバー側コードをそれぞれ含む、C 言語で書かれた単純な UDP 通信プログラムの例です。データグラムの送受信には、一般的なネットワークプログラミングインターフェースであるソケットAPIを使用します。

6.1 UDPサーバー

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 8888  // 服务器端口号
#define MAXLINE 1024  // 缓冲区大小

int main() {
    
    
    int sockfd;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_addr_len;
    char buffer[MAXLINE];
    ssize_t n;

    // 创建socket
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
    
    
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    memset(&server_addr, 0, sizeof(server_addr));
    memset(&client_addr, 0, sizeof(client_addr));

    // 服务器地址和端口的设置
    server_addr.sin_family = AF_INET;  // IPv4
    server_addr.sin_addr.s_addr = INADDR_ANY;  // 本机的任意IP
    server_addr.sin_port = htons(PORT);  // 端口号

    // 绑定socket和地址
    if (bind(sockfd, (const struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
    
    
        perror("bind failed");
        exit(EXIT_FAILURE);
    }

    while (1) {
    
    
        printf("Waiting for data...\n");

        client_addr_len = sizeof(client_addr);

        // 接收客户端的数据报
        n = recvfrom(sockfd, (char*)buffer, MAXLINE, 0, (struct sockaddr*)&client_addr, &client_addr_len);
        buffer[n] = '\0';  // 添加字符串结束符

        printf("Client: %s\n", buffer);

        // 将数据报发送回客户端
        sendto(sockfd, (char*)buffer, strlen(buffer), 0, (struct sockaddr*)&client_addr, client_addr_len);

        if (strncmp("exit", buffer, 4) == 0) {
    
    
            printf("Server Exit...\n");
            break;
        }
    }

    close(sockfd);

    return 0;
}

6.2 UDPクライアント

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 8888  // 服务器端口号
#define MAXLINE 1024  // 缓冲区大小

int main() {
    
    
    int sockfd;
    struct sockaddr_in server_addr;
    char buffer[MAXLINE];
    ssize_t n;

    // 创建socket
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
    
    
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    memset(&server_addr, 0, sizeof(server_addr));

    // 服务器地址和端口的设置
    server_addr.sin_family = AF_INET;  // IPv4
    server_addr.sin_addr.s_addr = INADDR_ANY;  // 服务器的IP地址
    server_addr.sin_port = htons(PORT);  // 端口号

    while (1) {
    
    
       

 printf("Enter message: ");
        fgets(buffer, sizeof(buffer), stdin);

        // 将数据报发送到服务器
        sendto(sockfd, (char*)buffer, strlen(buffer), 0, (struct sockaddr*)&server_addr, sizeof(server_addr));

        // 接收服务器的数据报
        n = recvfrom(sockfd, (char*)buffer, MAXLINE, 0, NULL, NULL);
        buffer[n] = '\0';  // 添加字符串结束符

        printf("Server: %s\n", buffer);

        if (strncmp("exit", buffer, 4) == 0) {
    
    
            printf("Client Exit...\n");
            break;
        }
    }

    close(sockfd);

    return 0;
}

注: 実際の運用では、サーバーとクライアントは異なるマシンまたは異なるプロセスで実行する必要があります。クライアント コード内のサーバー IP アドレスを実際のサーバー IP アドレスに置き換える必要があります。

この場合、UDP サーバーとクライアントの両方が無限ループを使用して、データグラムを継続的に送受信します。「exit」を入力するとループが終了し、サーバーとクライアントが終了します。

上の例では、次の重要なソケット API 関数を使用しました。

  • socket(): 新しいソケットを作成します。
  • bind(): ソケットを特定の IP アドレスとポート番号にバインドします。
  • sendto(): データグラムを特定のアドレスに送信します。
  • recvfrom(): 特定のアドレスからデータグラムを受信します。

この簡単な例は、UDP プロトコルを使用してデータを送受信する方法を示していますが、UDP プロトコルはデータの信頼性、順序、整合性を保証するものではないことに注意してください。実際のアプリケーションでは、これらの機能が必要な場合、TCP プロトコルを使用するか、アプリケーション層でこれらの機能を実装する必要がある場合があります。

おすすめ

転載: blog.csdn.net/weixin_52665939/article/details/131506118
おすすめ