【Linux】ネットワーク通信
記事ディレクトリ
1. ネットワーク基盤
1.1 コンピュータネットワーク
コンピュータ ネットワークの開発は、独立したモデルからネットワーク相互接続モデルに徐々に進化することができ、このプロセスは次の段階に分けることができます。
-
スタンドアロン モード:
コンピュータ ネットワークの初期の頃、各コンピュータは比較的独立した存在であり、他のコンピュータに接続されていませんでした。各コンピューターは個別のタスクにのみ使用され、データとリソースの共有は非常に限定されています。この段階では、コンピュータは主に科学計算とデータ処理に使用されます。 -
ピアツーピア接続:
コンピューターの数が増加するにつれて、人々はコンピューターを相互に接続することで、より効率的なリソースの共有と通信が可能になることに気づき始めました。そこで、2台のコンピュータを専用の通信回線で直接接続し、データ通信を可能にするポイントツーポイント接続のネットワークモデルが登場しました。このモードは初期の LAN でより一般的です。 -
ローカル エリア ネットワーク (LAN) の台頭:
コンピュータの数がさらに増加するにつれて、ローカル エリア ネットワーク (LAN) も台頭し始めました。LAN を使用すると、地理的に同じ場所にあるコンピュータを相互に接続して、リソースの共有と通信を行うことができます。イーサネット技術の発展により、コンピュータは共有物理媒体 (1 本のケーブルなど) を介して通信できるようになり、ローカル エリア ネットワークが可能になりました。 -
ワイド エリア ネットワーク (WAN) の出現:
コンピュータ ネットワークの発展に伴い、人々は地理的に広い範囲にわたって通信できるようになることを望んでいます。ワイド エリア ネットワーク (WAN) は、複数のローカル エリア ネットワークとポイントツーポイント接続を接続することにより、より広いエリアでコンピュータを相互接続するために登場しました。このネットワーク モードでは、ルーターとスイッチを使用して、異なるネットワーク間でデータを送信します。 -
インターネットの台頭:
インターネットは、コンピュータ ネットワークの発展における最高段階です。世界中のコンピュータネットワークを接続し、シームレスなデータ交換やリソース共有を実現します。インターネットは通信基盤として TCP/IP プロトコル スイートを使用し、さまざまな種類のネットワークやデバイスが相互に通信できるようにし、グローバルな情報交換プラットフォームを形成します。
1.2 ネットワークモデル
コンピュータ ネットワーク モデルは、コンピュータ ネットワーク内のさまざまなコンポーネント間の関係と通信を記述するために使用される抽象的なフレームワークです。一般的なコンピュータ ネットワーク モデルは次のとおりです。
-
OSI モデル (オープン システム相互接続モデル) :
OSI モデルは、国際標準化機構 (ISO) によって策定された 7 層のネットワーク モデルであり、各層は特定のネットワーク機能を表します。下から上に、物理層、データリンク層、ネットワーク層、トランスポート層、セッション層、プレゼンテーション層、アプリケーション層です。このモデルの主な目的は、異なるベンダーによって開発されたデバイス間の通信を容易にすることです。ただし、実際には、ほとんどのネットワークは、以下に説明する TCP/IP モデルを使用します。 -
TCP/IP モデル:
TCP/IP モデルは実際にインターネットで使用されており、ネットワーク インターフェイス層、ネットワーク層、トランスポート層、アプリケーション層の 4 つの層で構成されます。層の数は少ないものの、OSI モデルと同様の機能が含まれています。このモデルの名前は、伝送制御プロトコル (TCP) とインターネット プロトコル (IP) という 2 つのコア プロトコルに由来しています。 -
4 層ネットワーク モデル:
ネットワーク モデルには、ネットワークを物理層、データ リンク層、ネットワーク層、アプリケーション層の 4 層に分割するものがあります。このモデルでは、セッション層、プレゼンテーション層、トランスポート層が省略され、ネットワークの構造が簡素化されます。 -
5 層ネットワーク モデル:
このモデルは、ネットワークを物理層、データリンク層、ネットワーク層、トランスポート層、アプリケーション層の 5 層に分割します。機能的には TCP/IP モデルと似ていますが、含まれる層は 5 つだけです。
TCP/IP はプロトコルのグループの同義語であり、TCP/IP プロトコル クラスターを形成する多くのプロトコルも含まれます。TCP/IP プロトコル クラスターは 4 つの層に分かれており、IP はプロトコル クラスターの 2 層目 (OSI の 3 層目に相当) に位置し、TCP はプロトコル クラスターの 3 層目 (OSI の 4 層目に相当) に位置します。 OSI の層)。TCP/IP 通信プロトコルは 4 層の階層構造を採用しており、各層は次の層が提供するネットワークを呼び出して、それぞれのニーズを満たします。4 つの層は次のとおりです。
- アプリケーション層: Simple Email Transfer (SMTP)、File Transfer Protocol (FTP)、Network Remote Access Protocol (Telnet) などのアプリケーション間の通信のための層。
- トランスポート層: この層では、伝送制御プロトコル (TCP)、ユーザー データグラム プロトコル (UDP) などのノード間のデータ伝送サービスを提供します。TCP と UDP は、データ パケットに送信データを追加して次のパケットに送信します。 1 つの層では、この層はデータの送信と、データの送受信の確認を担当します。
- ネットワーク相互接続層: インターネット プロトコル (IP) など、基本的なデータ パケット送信機能を提供して、各データ パケットが宛先ホストに到達できるようにします (ただし、正しく受信されたかどうかはチェックしません)。
- ホストからネットワーク層: 実際のネットワーク メディアを管理し、実際のネットワーク (イーサネット、シリアル ラインなど) を使用してデータを送信する方法を定義します。
TCPとUDP
1) IPアドレス
2) ポート
1.さまざまなアプリケーションを区別するために使用されます
2.ポート番号の範囲は 0 ~ 65535 で、そのうち 0 ~ 1023 はシステムで予約されているポートではないため、プログラムではこれらのポートをできるだけ使用しないでください。
3. IP アドレスとポート番号はソケットを構成します。ソケットは、ネットワーク実行プログラム間の双方向通信リンクのエンドポイントであり、TCP と UDP の基礎です。
4.一般的なプロトコルで使用されるポート: HTTP: 80、FTP: 21、TELNET: 23
3) TCPプロトコルとUDPプロトコルの比較
詳細な TCP プロトコル プロセス:
まず、TCP/IP はプロトコル クラスターであり、多くのプロトコルが含まれています。UDP はその 1 つにすぎません。TCP/IP プロトコルと名付けられた理由は、TCP と IP プロトコルが 2 つの非常に重要なプロトコルであるため、それらにちなんで命名されたためです。
TCP プロトコルと UDP プロトコルの違いを説明しましょう。
TCP (Transmission Control Protocol、伝送制御プロトコル)はコネクション指向のプロトコル、つまりデータマネーを送受信する際には相手との信頼できるリンクを確立する必要があり、これもTCPの3ウェイハンドシェイクです。そしてインタビューでよく聞かれるTCPの4ウェイハンドシェイク!スリーウェイ ハンドシェイク: TCP 接続を確立するとき、クライアントとサーバーは接続の確立を確認するために合計 3 つのパケットを送信する必要があります。ソケット プログラミングでは、このプロセスはクライアントが connect を実行することによってトリガーされます。具体的なフローチャート以下のとおりであります:
- 最初のハンドシェイク: クライアントはフラグ ビット SYN を 1 に設定し、値 seq=J をランダムに生成し、データ パケットをサーバーに送信します。クライアントは SYN_SENT 状態に入り、サーバーの確認を待ちます。
- 2 回目のハンドシェイク: サーバーがデータ パケットを受信した後、フラグ ビット SYN=1 によりクライアントが接続の確立を要求していることがわかり、サーバーはフラグ ビット SYN と ACK を 1 (ack=J+1) に設定し、値をランダムに生成します。 seq=K で、データ パケットをクライアントに送信して接続要求を確認すると、サーバーは SYN_RCVD 状態に入ります。
- 3 回目のハンドシェイク: 確認を受信した後、クライアントは ack が J+1 であるかどうか、および ACK が 1 であるかどうかを確認します。それが正しい場合、フラグ ビット ACK が 1 (ack=K+1) に設定され、データ パケットが送信されます。がサーバーに送信されます。サーバーは、ack が K+1 であるかどうか、ACK が 1 であるかどうかを確認します。それが正しければ、接続は正常に確立されます。クライアントとサーバーは ESTABLISHED 状態になり、3 ウェイ ハンドシェイクが完了します。そうすると、クライアントとサーバーはデータの送信を開始できるようになります。
- 4 回振る: TCP 接続を終了します。つまり、TCP 接続を切断するとき、クライアントとサーバーは接続の切断を確認するために合計 4 つのパケットを送信する必要があります。ソケット プログラミングでは、このプロセスはクライアントまたはサーバーが close を実行することによってトリガーされます。具体的なフローチャートは次のとおりです。
- 第 1 波: クライアントは FIN を送信してクライアントからサーバーへのデータ送信を終了し、クライアントは FIN_WAIT_1 状態に入ります。
- 第 2 波: FIN を受信した後、サーバーはクライアントに ACK を送信し、シーケンス番号が受信したシーケンス番号 + 1 であることを確認します (SYN と同様、1 つの FIN が 1 つのシーケンス番号を占有します)。サーバーは CLOSE_WAIT 状態に入ります。 。
- 3 番目の波: サーバーは FIN を送信してサーバーからクライアントへのデータ送信を終了し、サーバーは LAST_ACK 状態に入ります。
- 4 番目のウェーブ: クライアントが FIN を受信した後、クライアントは TIME_WAIT 状態に入り、シリアル番号が受信したシリアル番号 + 1 であることを確認してサーバーに ACK を送信し、サーバーは CLOSED 状態に入り、完了します。 4人が手を振った。さらに、アクティブなシャットダウンが同時に開始される場合もあります。
さらに、接続を確立するには 3 ウェイ ハンドシェイクが必要ですが、接続を閉じるには 4 回のウェーブが必要なのはなぜですか?というよくある質問があるかもしれません。回答: サーバーは LISTEN 状態にあるため、接続確立要求の SYN メッセージを受信した後、ACK と SYN を 1 つのメッセージに含めてクライアントに送信します。接続を終了するとき、相手の FIN メッセージを受信したとき、それは相手がデータを送信しなくなったが、まだデータを受信できることを意味するだけであり、自分の当事者がすべてのデータを相手に送信していない可能性があるため、自分の当事者はデータが相手に送信された後、すぐに接続を閉じることに同意するために相手に FIN メッセージを送信するため、通常、自分の ACK と FIN は別々に送信されます。
UDPプロトコルの詳しい説明:
UDP (User Datagram Protocol) ユーザー データグラム プロトコルは非接続プロトコルであり、送信元と端末はデータを送信する前に接続を確立せず、送信する場合はアプリケーションからデータを取得し、できるだけ早く送信します。ネットワーク上に放り出されます。送信側では、UDP がデータを送信する速度は、アプリケーションがデータを生成する速度、コンピューターの機能、および送信帯域幅によってのみ制限されます。メッセージ セグメントを読み取ります。TCPと比較すると、リンクを張る必要がなく、構造が単純で、正当性が保証されず、パケットが失われやすい
1.3 ネットワーク伝送
ネットワーク伝送とネットワーク モデルの間には密接な関係があり、ネットワーク モデルは、ネットワーク伝送の構造化されたフレームワークとガイドラインを提供し、ネットワーク内のデータ伝送プロセスの理解と体系化に役立ちます。
TCP/IP プロトコル クラスターは、物理層、データ リンク層、ネットワーク層、トランスポート層、アプリケーション層の 5 つの層を含む一連のプロトコルです。各層には特定の機能とタスクがあります。
-
物理層: イーサネット、光ファイバー、無線ネットワークなどの光/電気信号の伝送を担当します。ハブはこの層で動作します。
-
データリンク層: データフレームの送信と識別、フレーム同期の処理、衝突検出、データエラーチェックを行います。スイッチはこの層で動作します。
-
ネットワーク層: アドレス管理とルーティング選択を実行し、IP アドレスを通じてホストを識別し、データ伝送パスを計画します。ルーターはこの層で動作します。
-
トランスポート層: 信頼性の高いデータ伝送を保証するための TCP プロトコルなど、ホスト間のデータ伝送を担当します。
-
アプリケーション層: 電子メール転送 (SMTP)、ファイル転送 (FTP)、リモート アクセス (Telnet) など、アプリケーション間の通信を処理します。
5 層構造が連携して TCP/IP プロトコル クラスターを形成し、現代のコンピューター ネットワークのさまざまな通信およびデータ送信機能をサポートします。
ホストの場合、そのオペレーティング システム カーネルはトランスポート層から物理層までのコンテンツを実装します。
ルーターの場合、ネットワーク層から物理層までを実装します。
スイッチの場合、データリンク層から物理層までを実装します。
ハブの場合、物理層のみを実装します。
1.3.1 送信ロジック
データ送信のロジックは次のように要約できます。
-
準備段階:
- アプリケーション層では、送信するデータを準備し、データ形式や処理ロジックを定義します。
- HTTP、FTP などの適切なアプリケーション層プロトコルを選択して、データ送信方法とルールを決定します。
-
トランスポート層プロトコルの選択:
- アプリケーションの要件に応じてトランスポート層プロトコルを選択し、信頼性の要件が高い場合は TCP を、リアルタイム性の要件が高い場合は UDP を選択します。
-
接続を確立してリッスンします。
- TCPの場合は接続を確立する必要があります。送信者と受信者の間に接続が確立され、信頼性の高いデータ送信が保証されます。
- UDPの場合、接続は必要ありませんが、データの送受信の宛先アドレスを決定する必要があります。
-
データのカプセル化とヘッダー情報:
- 送信側では、アプリケーション層のデータをパケットにカプセル化し、適切なトランスポート層とネットワーク層のヘッダー情報を追加します。
- ヘッダー情報には IP アドレス、ポート番号などが含まれており、ルーティングや対象デバイスの識別に使用されます。
-
データ転送:
- トランスポート層プロトコルは、エラー検出やフロー制御などの操作を実行しながら、カプセル化されたデータ パケットをターゲット デバイスに送信する役割を果たします。
- ネットワーク層プロトコルは、ターゲット IP アドレスに応じて適切なルートを選択し、データ パケットの送信経路を決定します。
-
物理的な輸送:
- リンク層はデータ パケットをフレームにカプセル化し、リンク層のヘッダーとテールを追加して、物理媒体を介して受信側に送信します。
-
データの解凍と処理:
- 受信側では、リンク層がフレームを受信して解析し、データをネットワーク層に渡します。
- ネットワーク層は、IP アドレスに基づいてターゲット デバイスを決定し、データをトランスポート層に渡します。
-
データの再編成と解析:
- トランスポート層プロトコルは、受信したデータ パケットを順番に再構成し、エラーの検出と訂正を実行し、データをアプリケーション層に配信する責任を負います。
-
アプリケーション層の処理:
- アプリケーションはデータ パケットを解析し、定義されたデータ形式に従ってデータ コンテンツを処理し、対応するビジネス ロジックを実行します。
この論理プロセスは、アプリケーション層から物理層までのデータ送信のすべての段階とプロセスをカバーし、特定のルールと手順に従ってデータが送信および処理されることを保証します。
1.3.2 送信条件
データ伝送の前提条件は、アプリケーション層、トランスポート層、ネットワーク層、リンク層に応じて次のように分類されます。
アプリケーション層:
- 通信機器: 通信機器は2台以上必要です。
- IP アドレスとポート番号: 各デバイスには一意の IP アドレスと適切なポート番号が必要です。
- データ形式の定義: 送信者と受信者がデータを正しく解析して処理できるように、データの形式を定義する必要があります。
- セキュリティに関する考慮事項: 特に機密情報の送信については、データのセキュリティと暗号化を考慮する必要があります。
トランスポート層:
- プロトコルの選択: データ伝送要件に応じて、TCP や UDP などの適切なトランスポート層プロトコルを選択する必要があります。
- トランスポート メカニズム: 接続の確立、データの転送、トラフィックの管理、接続の終了方法を理解する必要があります。
- エラー処理メカニズム: パケット損失や再送信など、データ伝送で起こり得るエラーを考慮する必要があります。
ネットワーク層:
- ネットワーク接続: 通信デバイスは、有線または無線のネットワークを介して相互に接続する必要があります。
- IP アドレス: 各デバイスには、ネットワーク内のデバイスを識別するために使用される一意の IP アドレスが必要です。
- ルーティング: データパケットの伝送経路を選択するにはルーティングプロトコルを使用する必要があります。
リンク層:
- 物理接続: 通信デバイスはイーサネットや電波などの物理レベルで接続する必要があります。
- リンク アドレス: リンク層は、MAC アドレスなどの各デバイスの物理アドレスを決定する必要があります。
1.3.3 送信プロセス
日常生活で電子メールを送信する場合、TCP/IP プロトコル送信の具体的なプロセスを次の表に示します。
ステップ | レベル | アクションとヘッダー |
---|---|---|
1 | アプリケーション層 | メールを書き、メールの内容を準備します。 |
2 | アプリケーション層 | 電子メール クライアントを使用します。 |
3 | アプリケーション層 | メールデータをカプセル化します。 |
4 | トランスポート層 | TCPプロトコルを選択します。 |
5 | トランスポート層 | TCP接続を確立します。 |
6 | トランスポート層 | メールデータをTCPパケットにカプセル化します。 |
7 | ネットワーク層 | IP アドレスを選択します。 |
8 | ネットワーク層 | TCP パケットを IP パケットにカプセル化します。 |
9 | リンク層 | リンク層ヘッダーのフレーム化と追加。 |
10 | リンク層 | 物理メディアを介してデータを転送します。 |
11 | リンク層 | データ フレームを解析し、リンク層ヘッダーを削除します。 |
12 | ネットワーク層 | IP データ パケットを分析してターゲット IP を取得します。 |
13 | トランスポート層 | TCP はパケットを再構築してチェックします。 |
14 | トランスポート層 | パケットをアプリケーション層に渡します。 |
15 | アプリケーション層 | 電子メール データを解析し、電子メールのコンテンツを処理します。 |
16 | アプリケーション層 | メールの処理を続行し、場合によっては転送します。 |
1.4 アドレス管理
ネットワーク アドレスは、コンピュータ ネットワーク内のさまざまなデバイスやホストを識別するために存在します。さまざまなレベルのネットワーク モデルでは、データ送信中にネットワーク アドレスを使用してデータの送信者と受信者を決定する必要があります。
-
物理層: 物理層は信号の送信を担当しますが、信号が正しいデバイスに確実に到達するために、各デバイスはネットワーク内で一意の物理アドレス (MAC アドレス) を持っている必要があります。これは、ローカル エリア ネットワーク上のデバイスを識別するためにデータ リンク層で使用されるアドレスです。
-
データ リンク層: データ リンク層では、デバイスがデータを正しく送受信できるように、データ フレームは宛先 MAC アドレスと送信元 MAC アドレスを運ぶ必要があります。これらのアドレスは、ローカル エリア ネットワーク内のデバイスを識別するために使用されます。
-
ネットワーク層: ネットワーク層では、IP アドレスを使用してさまざまなホストとルーターを識別します。IP アドレスはターゲット デバイスをグローバルに検索するために使用され、異なるネットワーク間でデータを送信できるようになります。
-
トランスポート層: トランスポート層では、データには送信元ポート番号と宛先ポート番号が含まれます。これらのポート番号は一緒になって、さまざまなアプリケーションとサービスを識別するソケットを形成します。これらは、トランスポート層がデータを適切なアプリケーションに配信するのに役立ちます。
結論として、アドレスはさまざまなネットワーク層で重要な役割を果たし、さまざまなデバイス、ホスト、サービスを識別するために使用されます。これらは、データがネットワーク上で正しく移動することを保証し、通信をスムーズに進めるのに役立ちます。
2. ネットワークプログラミング
2.1 基本概念
2.1.1 IPアドレス
IP アドレス (インターネット プロトコル アドレス) は、コンピュータ ネットワーク内のデバイスを一意に識別し、位置を特定するために使用されるデジタル ラベルです。これはインターネット プロトコル スイートの一部であり、ネットワーク内でのデータ パケットのルーティングと配信に使用されます。IP アドレスは、データが送信者から受信者に正確に配信されることを保証するためのメールアドレスのように機能します。
IP アドレスの基本概念は次のとおりです。
-
固有の識別:各デバイス (コンピューター、サーバー、ルーター、モバイル デバイスなど) には、ネットワーク内で固有の IP アドレスが割り当てられます。これは、パケットが正しくルーティングされ、配信されることを保証するのに役立ちます。
-
階層構造: IP アドレスは通常、IPv4 (インターネット プロトコル バージョン 4) と IPv6 (インターネット プロトコル バージョン 6) の 2 つの主要なバージョンに分かれています。IPv4 は 32 ビットの 2 進数を使用して表され、通常はドット付き 10 進表記で表されます (たとえば、192.168.1.1)。IPv6 は 128 ビットの 2 進数を使用して表され、より複雑な方法で表示されます (たとえば、2001:0db8:85a3:0000:0000:8a2e:0370:7334)。
-
IPv4 アドレスの枯渇:インターネットの急速な拡大により、IPv4 アドレス空間はほとんど枯渇しました。これにより、将来的により多くの接続デバイスをサポートできる大規模なアドレス空間が提供される IPv6 が導入されました。
-
パブリック アドレスとプライベート アドレス: IP アドレスはパブリックまたはプライベートにすることができます。パブリック IP アドレスは世界的に一意であり、インターネットへの直接アクセスに使用されます。プライベート IP アドレスは、ローカル エリア ネットワーク (家庭や企業のイントラネットなど) 内で使用され、インターネットに直接公開されることはありません。
-
サブネット マスク:サブネット マスクは、どの部分がネットワーク部分で、どの部分がホスト部分であるかを示すために、IP アドレスと組み合わせて使用されるパラメーターです。これは、IP アドレスをネットワークとホストに分割して、サブネット内でのルーティングをより効率的にするのに役立ちます。
-
DHCP と静的 IP: IP アドレスは、動的ホスト構成プロトコル (DHCP) 経由で自動的に割り当てることも、静的 IP アドレスとして手動で構成することもできます。DHCP を使用すると、ネットワーク デバイスがネットワークに参加するときに、IP アドレスやその他のネットワーク構成情報を自動的に取得できます。
-
ネットワーク層アドレス: IP アドレスはネットワーク層 (層 3) プロトコルにあり、送信元ホストから宛先ホストへのデータ パケットの送信を担当します。MAC アドレス (データ リンク層、レイヤー 2) と連携して、異なるネットワーク間でデータを転送します。
IP アドレスはインターネット通信の基礎であり、これを通じてデータを正確かつ確実に世界中に送信できます。Web の閲覧、電子メールの送信、ビデオ通話のいずれにおいても、IP アドレスは舞台裏で重要な役割を果たします。
協定との関係
IP アドレスはインターネット プロトコル スイートの重要な概念であり、他の複数のプロトコルと連携してネットワーク内でのデータの送信と通信を実現します。IP アドレスが他の重要なプロトコルとどのように関係するかは次のとおりです。
-
TCP/IP プロトコル スタック: TCP/IP は、インターネットの基礎を形成する一連のネットワーク プロトコルです。IP アドレスは、TCP/IP プロトコル スタックのコア コンポーネントです。TCP (伝送制御プロトコル) は、通信する 2 つの当事者間で信頼性の高い接続とデータ送信を確立する役割を果たします。一方、IP は、送信元ホストから宛先ホストへのデータ パケットのルーティングを担当します。
-
MAC アドレス: MAC アドレス (メディア アクセス コントロール アドレス) は、ローカル エリア ネットワーク内のネットワーク デバイスを一意に識別するために使用されるデータ リンク層 (レイヤー 2) の識別子です。IPアドレス(第3層のネットワーク層に位置します)はMACアドレスと連携し、ARP(Address Resolution Protocol)などの仕組みにより、IPアドレスと対応するMACアドレスがマッピングされてLAN内でのデータ伝送が実現されます。
-
ARP プロトコル: ARP (アドレス解決プロトコル) は、IP アドレスを対応する MAC アドレスに解決するために使用されます。デバイスが別のデバイスにデータを送信する必要がある場合、ターゲット デバイスの MAC アドレスを知っている必要があります。ARP プロトコルは、ホストが同じ LAN 内の IP アドレスに対応する MAC アドレスを見つけるのに役立ちます。
-
DHCP プロトコル: DHCP (動的ホスト構成プロトコル) は、ネットワークに参加する新しいデバイスに IP アドレスおよびその他のネットワーク構成情報を自動的に割り当てるために使用されます。DHCP サーバーは、使用可能な IP アドレスをクライアントに割り当て、IP アドレスを手動で構成しなくても、デバイスがネットワークにすぐに接続できるようにします。
-
DNS プロトコル: DNS (ドメイン ネーム システム) は、覚えやすいドメイン名を IP アドレスに変換します。インターネットでは、複雑な IP アドレスよりもドメイン名 (www.example.com など) の方が覚えやすいです。DNS プロトコルを使用すると、ドメイン名が対応する IP アドレスに解決され、ユーザーが Web サイトやリソースにアクセスできるようになります。
-
ICMP プロトコル: ICMP (Internet Control Message Protocol) は、IP ネットワークでエラー メッセージと制御メッセージを送信するために使用されます。たとえば、転送中のパケットに問題が発生した場合、ICMP はエラー メッセージを生成し、送信元ホストに通知できます。
これらのプロトコルは相互に連携して、インターネット通信の基本構造を形成します。IP アドレスはこれらのプロトコル間のブリッジとして機能し、ネットワークのさまざまな層でデータを送信および交換できるようにします。
2.1.2 ポート番号
コンピュータ ネットワーキングにおいて、ポート番号は、特定のアプリケーションまたはサービスを識別するために使用される数値識別子です。TCP (Transmission Control Protocol) や UDP (User Datagram Protocol) などのトランスポート層プロトコルで使用される概念です。IP アドレスとポート番号を組み合わせることで、ネットワーク内の異なるアプリケーションを同じデバイス上で同時に実行でき、データの多重化と分散が可能になります。
ポート番号の主な意味をいくつか示します。
-
アプリケーションの識別:ポート番号は、デバイス上で実行されているさまざまなアプリケーションまたはサービスを識別するために使用されます。各アプリケーションは、他のデバイスと通信するために 1 つ以上の特定のポート番号をリッスンできます。
-
多重化:ポート番号を使用すると、複数のアプリケーションを互いに干渉することなく同じデバイス上で同時に実行できます。トランスポート層プロトコルは、宛先ポート番号に基づいてパケットを正しいアプリケーションに配信できます。
-
データ送信:ポート番号と IP アドレスはネットワーク ソケット (ソケット) を構成し、アプリケーションがネットワーク経由でデータを送信できるようにします。送信元ポート番号は送信者によって使用され、宛先ポート番号は受信者によって使用され、データをどのアプリケーションに配信するかを決定します。
-
サービス識別:いくつかの標準ポート番号は、特定のサービスまたはプロトコルに割り当てられています。たとえば、HTTP は通常ポート番号 80 を使用し、HTTPS はポート番号 443 を使用し、SMTP (メール転送) はポート番号 25 を使用します。これにより、ネットワーク デバイスとアプリケーションは共通のサービスを認識し、データを正しいポートに渡すことができます。
-
セキュリティ:ポート番号はネットワーク セキュリティにも関係します。ファイアウォールとネットワーク セキュリティ デバイスは、ポート番号に基づいてデータ トラフィックを制御し、特定のアプリケーションやサービスの通信を許可またはブロックできます。
-
動的割り当て:いくつかの一般的な標準ポート番号に加えて、アプリケーションは動的に割り当てられたポート番号を使用することもできます。これらのポート番号は、通信中にアプリケーションに一時的に割り当てられ、通信終了後に解放して再利用できます。
ポート番号はネットワーク通信における重要な概念であり、これにより、異なるアプリケーションが同じデバイス上のネットワークを介して通信できるようになり、データがターゲット アプリケーションに正確に配信されることが保証されます。
2.1.3 ネットワークのバイトオーダー
ネットワーク バイト オーダー (ネットワーク バイト オーダー) では、コンピューター ネットワーク内の異なるコンピューター アーキテクチャ (ビッグ エンディアンとリトル エンディアンなど) 間でデータを送信するときのバイト オーダーの問題について説明します。コンピュータ アーキテクチャが異なると、メモリ内にマルチバイト データ (整数、浮動小数点数など) のエンディアンが異なる方法で保存されるため、ネットワーク通信におけるデータの混乱や誤解が生じる可能性があります。
ネットワーク通信には、複数のコンピュータまたはデバイス間でのデータ交換が含まれます。異なるデバイスが異なるエンディアンを使用すると、データの送信時に次の問題が発生する可能性があります。
-
データの誤解:バイトの順序が送信者と異なるため、受信者はデータを誤解する可能性があります。これにより、受信側のアプリケーションでデータが誤って解釈され、処理される可能性があります。
-
データの切り捨て:送受信時にデータが異なるエンディアンで送信されると、データの部分的な切り捨てや損失が発生する可能性があります。これにより、データの整合性が損なわれる可能性があります。
これらの問題を解決するには、ネットワーク通信で一貫したエンディアンを使用して、異なるデバイス間でデータを正しく受け渡し、解釈できるようにする必要があります。この一貫したバイト順序はネットワーク バイト順序と呼ばれ、通常はビッグ エンディアンです。
ネットワーク バイト オーダーの議論には、データ送信中に送信側と受信側の両方がデータを正しく解釈できるようにする方法が含まれます。htonl()
これを実現するには、htons()
、 、ntohl()
などのエンディアン変換関数をntohs()
使用して、異なるエンディアンネス間で変換します。これにより、ビッグ エンディアンが使用されているかリトル エンディアンが使用されているかに関係なく、ネットワーク全体でデータが一貫して送信され、解釈されることが保証されます。
2.2 TCPベースのソケット通信
2.2.1 ソケットについて
ソケット (Socket) は、コンピュータ ネットワークで通信するために使用されるプログラミング インターフェイス (API) です。ネットワークを介して異なるコンピュータ間でデータを送信し、プロセス間通信を実現するメカニズムを提供します。
背景と問題:初期のコンピュータ ネットワークでは、異なるデバイス間で通信する方法が必要でした。初期のネットワーク通信は低レベルのネットワーク プロトコルを通じて実行されますが、これはアプリケーションにとって煩雑すぎます。開発者は、アプリケーション間のデータ交換を可能にするために通信の詳細を処理するためのより高いレベルの抽象化を必要とします。
問題解決と方法: Socket インターフェースの登場により、上記の問題は解決されました。アプリケーションがデータを簡単に作成、接続、送信、受信できるようにする標準 API を提供します。Socket を使用すると、アプリケーション プログラムは基礎となるネットワークの詳細を気にする必要がなく、通信を実現するために Socket 関数を使用するだけで済みます。
役割:ソケットはネットワーク通信において重要な役割を果たし、アプリケーションが異なるデバイス間でデータを簡単に交換できるようにします。開発者は、Socket を介して、オンライン ゲーム、チャット アプリケーション、ファイル転送ツール、ネットワーク サーバーなどのさまざまなネットワーク アプリケーションを構築できます。
開発プロセスと変更: Socket の開発はさまざまな段階を経ました。当初、それは伝統的な Unix ファイル I/O に基づいていましたが、その後、コンピュータ ネットワークの発展に伴い、ソケットは徐々に標準化され、さまざまなソケット タイプ (ストリーム ソケット、データグラム ソケットなど) やソケット機能 (ソケット()、バインド()、接続()、send()、recv()など)。ネットワーク技術の進歩に伴い、Socket はさまざまなオペレーティング システムやプログラミング言語で広くサポートされるようになりました。
さらに、インターネットの急速な発展に伴い、Socket の応用範囲は従来のネットワーク通信から Web 開発、リアルタイムの音声とビデオの送信、クラウド コンピューティングなどの分野まで広がっています。同時に、HTTP、FTP、SMTP などのさまざまな高度な通信プロトコルも Socket に基づいて構築されています。
つまり、ソケットはネットワーク プログラミングの中核概念であり、コンピューター ネットワーク通信において非常に重要な役割を果たし、アプリケーションが基礎となる詳細を扱うことなくネットワーク間で簡単に通信できるようにするための共通インターフェイスを提供します。Unix ファイル I/O の初期開発から最新のネットワーク通信に至るまで、Socket は変化するネットワーク要件に適応するために常に進化してきました。
2.2.2 通信模型
ソケット通信の実装手順の分析:
ステップ 1 : ServerSocket とソケットを作成する
ステップ 2 : に接続されているソケットの入出力ストリームを開きます。
ステップ 3 : プロトコルに従ってソケットの読み取り/書き込みを行う
ステップ 4 : 入力ストリームと出力ストリーム、およびソケットを閉じる
次に、簡単な例を作成します。サーバーを起動した後、クライアントはボタンをクリックしてサーバーに接続し、サーバーがソケットを介してサーバーに接続されていることを示す文字列をサーバーに送信します。
2.2.3 サーバーの作成
サーバーが行う必要があることは次のとおりです。
ステップ 1 : ServerSocket オブジェクトを作成し、リスニング ポートをバインドする
ステップ 2 : accept() メソッドを呼び出してクライアントのリクエストを監視する
ステップ 3 : 接続が確立された後、入力ストリームを通じてクライアントによって送信されたリクエスト情報を読み取ります。
ステップ 4 : 出力ストリームを通じて応答情報をクライアントに送信する
ステップ 5 : 関連リソースを閉じる
コード:
#include <iostream>
#include <cstring>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
int main() {
int serverSocket, clientSocket;
struct sockaddr_in serverAddr;
struct sockaddr_in clientAddr;
socklen_t clientAddrLen = sizeof(clientAddr);
// 1. 创建服务器端 Socket
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
// 配置服务器地址
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = INADDR_ANY; // 任意地址
serverAddr.sin_port = htons(12345); // 端口号转换为网络字节序
// 2. 绑定端口和地址
bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
// 3. 监听连接请求
listen(serverSocket, 5); // 允许最大排队连接数为5
std::cout << "~~~ 服务端已就绪,等待客户端接入 ~~~" << std::endl;
// 4. 等待客户端连接
clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddr, &clientAddrLen);
char clientIp[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(clientAddr.sin_addr), clientIp, INET_ADDRSTRLEN);
std::cout << "客户端接入,客户端 IP 地址:" << clientIp << std::endl;
// 5. 读取客户端信息
char buffer[1024];
memset(buffer, 0, sizeof(buffer));
while (recv(clientSocket, buffer, sizeof(buffer), 0) > 0) {
std::cout << "客户端发送过来的信息:" << buffer << std::endl;
memset(buffer, 0, sizeof(buffer));
}
// 6. 关闭连接
close(clientSocket);
close(serverSocket);
return 0;
}
2.2.4 クライアントの書き込み
クライアントがしなければならないことは次のとおりです。
ステップ 1 : リンクするサーバーのアドレスとポート番号を示す Socket オブジェクトを作成します。
ステップ 2 : リンクが確立された後、出力ストリームを通じてリクエスト情報をサーバーに送信します。
ステップ 3 : 出力ストリームを通じてサーバー応答情報を取得する
ステップ 4 : 関連リソースを閉じる
コード:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
int main() {
// 创建客户端 Socket
int clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket == -1) {
std::cerr << "Error creating socket!" << std::endl;
return 1;
}
// 配置服务器地址和端口
struct sockaddr_in serverAddr;
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(12345); // 端口号转换为网络字节序
if (inet_pton(AF_INET, "172.16.2.54", &serverAddr.sin_addr) <= 0) {
std::cerr << "Invalid address or address family!" << std::endl;
return 1;
}
// 连接到服务器
if (connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == -1) {
std::cerr << "Error connecting to server!" << std::endl;
close(clientSocket);
return 1;
}
// 获取客户端 IP 地址
char clientIp[INET_ADDRSTRLEN];
if (inet_ntop(AF_INET, &serverAddr.sin_addr, clientIp, INET_ADDRSTRLEN) == nullptr) {
std::cerr << "Error converting IP address!" << std::endl;
close(clientSocket);
return 1;
}
// 发送消息到服务器
const char* message = "客户端:";
send(clientSocket, message, strlen(message), 0);
send(clientSocket, clientIp, strlen(clientIp), 0);
send(clientSocket, " 接入服务器!", strlen(" 接入服务器!"), 0);
// 关闭连接
close(clientSocket);
return 0;
}
2.3 UDPに基づく
2.3.1 サーバーの実装
サーバーの実装手順:
ステップ 1 : DatagramSocket を作成し、ポート番号を指定します
ステップ 2 : DatagramPacket を作成します
ステップ 3 : クライアントから送信されたデータ情報を受信します
ステップ 4 : データを読み取ります
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <arpa/inet.h>
#include <unistd.h>
int main() {
/*
* 接收客户端发送的数据
*/
// 1. 创建服务器端套接字
int serverSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (serverSocket == -1) {
std::cerr << "Error creating socket!" << std::endl;
return 1;
}
// 2. 配置服务器地址
struct sockaddr_in serverAddr;
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = INADDR_ANY; // 使用本地所有可用地址
serverAddr.sin_port = htons(12345); // 端口号转换为网络字节序
// 3. 绑定端口和地址
if (bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == -1) {
std::cerr << "Error binding socket!" << std::endl;
close(serverSocket);
return 1;
}
// 4. 接收客户端发送的数据
struct sockaddr_in clientAddr;
socklen_t clientAddrLen = sizeof(clientAddr);
char data[1024];
memset(data, 0, sizeof(data));
std::cout << "**** 服务器端已经启动,等待客户端发送数据 ****" << std::endl;
ssize_t bytesRead = recvfrom(serverSocket, data, sizeof(data), 0, (struct sockaddr*)&clientAddr, &clientAddrLen);
if (bytesRead == -1) {
std::cerr << "Error receiving data!" << std::endl;
close(serverSocket);
return 1;
}
data[bytesRead] = '\0'; // 添加字符串结尾标志
std::cout << "我是服务器,客户端说:" << data << std::endl;
/*
* 向客户端响应数据
*/
// 1. 获取客户端的地址和端口
struct sockaddr_in responseAddr = clientAddr;
socklen_t responseAddrLen = sizeof(responseAddr);
// 2. 定义响应的数据
const char* responseMsg = "欢迎您!";
// 3. 响应客户端
ssize_t bytesSent = sendto(serverSocket, responseMsg, strlen(responseMsg), 0, (struct sockaddr*)&responseAddr, responseAddrLen);
if (bytesSent == -1) {
std::cerr << "Error sending response!" << std::endl;
}
// 4. 关闭套接字
close(serverSocket);
return 0;
}
2.3.2 クライアントの実装
クライアントの実装手順:
ステップ 1 : 送信情報を定義する
ステップ 2 : 送信する情報を含む DatagramPacket を作成する
ステップ 3 : DatagramSocket を作成する
ステップ 4 : データを送信する
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <arpa/inet.h>
#include <unistd.h>
int main() {
/*
* 向服务器端发送数据
*/
// 1. 定义服务器地址和端口号
struct sockaddr_in serverAddr;
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(8800); // 端口号转换为网络字节序
if (inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr) <= 0) {
std::cerr << "Invalid address or address family!" << std::endl;
return 1;
}
// 2. 定义要发送的数据
const char* data = "用户名:admin;密码:123";
// 3. 创建 UDP 套接字
int clientSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (clientSocket == -1) {
std::cerr << "Error creating socket!" << std::endl;
return 1;
}
// 4. 发送数据报到服务器
ssize_t bytesSent = sendto(clientSocket, data, strlen(data), 0, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if (bytesSent == -1) {
std::cerr << "Error sending data!" << std::endl;
close(clientSocket);
return 1;
}
/*
* 接收服务器端响应的数据
*/
// 1. 创建用于接收数据的缓冲区
char reply[1024];
memset(reply, 0, sizeof(reply));
// 2. 接收服务器响应的数据
struct sockaddr_in responseAddr;
socklen_t responseAddrLen = sizeof(responseAddr);
ssize_t bytesRead = recvfrom(clientSocket, reply, sizeof(reply), 0, (struct sockaddr*)&responseAddr, &responseAddrLen);
if (bytesRead == -1) {
std::cerr << "Error receiving data!" << std::endl;
} else {
std::cout << "我是客户端,服务器说:" << reply << std::endl;
}
// 3. 关闭套接字
close(clientSocket);
return 0;
}