ソケットの詳しい紹介

序文

この記事は Socket 通信に関するごった煮です。私は自分の限界や欠点をよく知っていますが、言語表現、論理的思考、知識の蓄えなど、改善し学ぶべき点はたくさんあります。したがって、私のブログに間違いや不正確な点、または補足が必要な点を見つけた場合は、修正や提案をお願いします。

1-ソケットが現れる理由

1.1-ソケットの背景

ソケット (Socket) は、ネットワーク通信用のプログラミング インターフェイス (API) であり、異なるオペレーティング システムやプログラミング言語間でアプリケーションが相互に通信できるようにする標準化された方法を提供します。ソケットはもともと、異なるホスト間のプロセス間通信を目的として、BSD (Berkeley Software Distribution) オペレーティング システムで開発されました。BSD は、カリフォルニア大学バークレー校によって開発された Unix オペレーティング システムの一分野であり、ソケットの定義と実装は事実上の標準となっています。その後、インターネットの発展により、Socket はネットワーク プログラミングで広く使用されるようになりました。

初期のコンピュータ ネットワークでは、通信にさまざまなプロトコルが使用されていましたが、これらのプロトコル間に標準化されたインターフェイスがなかったため、アプリケーションを作成して移植することが非常に困難でした。この問題を解決するために、一部のコンピュータ科学者は、異なるコンピュータが通信できるように標準の通信インターフェイスを定義する方法を研究し始めました。このような背景のもとに Socket が誕生し、アプリケーションが異なるオペレーティング システムとコンピュータ間で通信できるようにする、移植可能で拡張性があり、使いやすいインターフェイスを提供します。

インターネットの発展に伴い、Socket はネットワーク プログラミングに不可欠な部分になりました。Webサーバー、電子メールクライアント、チャットプログラムなど、さまざまなネットワークアプリケーションで広く使用されています。同時に、コンピューター ハードウェアとネットワーク テクノロジの継続的な開発に伴い、Socket も常に更新され、新しいアプリケーション シナリオとニーズに適応するために改良されています。

1.2-ソケットが問題を解決する

ソケット通信は、主にコンピュータネットワークにおけるプロセス間通信の問題を解決するために使用されます。ネットワーク プログラミングでは、特定のタスクを完了するために通信する必要がある 2 つのプロセスがあり、これら 2 つのプロセスは異なるコンピュータ上で実行される場合もあれば、同じコンピュータ上の異なるプロセスで実行される場合もあります。ソケットは、これらのプロセスがネットワーク内でデータを交換し通信できるようにする標準化されたインターフェイスを提供します。具体的には、ソケット通信は次の問題を解決できます。

  1. プロセス間通信: 同じコンピュータ上では、異なるプロセスが相互に通信する必要があります。ソケットは、プロセスがネットワーク経由で通信できるようにする標準化されたインターフェイスを提供します。
  2. クロスプラットフォーム通信: 異なるコンピューター、オペレーティング システム、プログラミング言語が通信する必要があるため、ソケットは、アプリケーションが異なるプラットフォーム上で実行および通信できるようにするポータブル インターフェイスを提供します。
  3. ネットワーク通信のセキュリティ: ネットワーク通信には情報漏洩、データ改ざん、サービス妨害攻撃などのセキュリティ問題がありますが、Socketでは暗号化、本人認証、ファイアウォールにより通信セキュリティを向上できます。
  4. 通信プロトコル: ソケットは柔軟な通信プロトコルを提供し、TCP、UDP、その他のプロトコルなど、特定の通信要件を満たすためにニーズに応じてさまざまなプロトコルを選択できます。

つまり、ソケット通信は、標準化された信頼性が高く安全なネットワーク通信方法をアプリケーションに提供し、異なるコンピュータ間でアプリケーションがデータ交換、情報共有、リモート制御などの操作を実行できるようにします。

2ソケットの構成とポイント

2.1-内容: ソケットとは何ですか?

Socket の原義は「ソケット」で、コンピュータ通信の分野では「ソケット」と訳され、コンピュータ間の通信の約束事や方法のことです。ソケットは本質的には抽象化層です。これは、一連の関数とデータ構造を含む、ネットワーク通信用の API のセットです。アプリケーションがネットワーク内でデータを送信できるように、標準のネットワーク プログラミング インターフェイスを提供します。ソケット自体は具体的な実装ではなく、抽象的な概念です。オペレーティング システムやプログラミング言語が異なれば、ソケット API をさまざまな方法で実装できます。
ソケット契約を通じて、コンピュータは他のコンピュータからデータを受信したり、他のコンピュータにデータを送信したりすることができます。socket() 関数は整数のソケット記述子を返し、接続の確立やデータ送信などの後続の操作はすべてこのソケットを通じて実装されます。

ソケットは Unix に由来しており、Unix/Linux の基本理念の 1 つは「すべてはファイルである」であり、「開くオープン –> 読み取りと書き込み書き込み/読み取り –> 閉じるクローズ」のモードで動作します。Unix/Linux システムでは、ソケットも特殊なファイルであり、一部のソケット関数はそのファイルに対する操作 (読み取り/書き込み IO、オープン、クローズ) です。socket() 関数を使用してネットワーク接続を作成したり、ネットワーク ファイルを開くことができます。socket() の戻り値はファイル記述子です。ファイル記述子を使用すると、次のような一般的なファイル操作関数を使用してデータを転送できます。

  • read() を使用して、リモート コンピューターから送信されたデータを読み取ります。

  • write() を使用して、リモート コンピューターにデータを書き込みます。

    接続がsocket()で確立されていれば、あとはファイル操作です。

ソケットは電話線や電線に例えることができます。電話線や電線が信頼性の高い通信チャネルを提供し、2 か所間の音声やデータ通信を可能にするのと同じように、ソケットも信頼性の高い通信チャネルを提供し、データの交換と通信を可能にします。 2台のコンピュータ間で可能です。電話をかけたりメッセージを送信したりするときに接続を確立し、データを送信し、その後切断する必要があるのと同じように、Socket も接続を確立し、データを送信し、最後に接続を閉じる必要があります。電話線や電線がさまざまな通信プロトコルやデータ型をサポートできるのと同じように、Socket もさまざまなネットワーク プロトコルやデータ形式をサポートできます。

ネットワーク プログラミングでは、通常、ソケットは次のタイプのネットワーク通信を実装するために使用されます。

  1. ストリーミング ソケット (TCP ソケット): TCP プロトコルに基づいて、大量のデータを送信するアプリケーションやデータの整合性と信頼性を必要とするアプリケーションに適した、信頼性の高い接続指向の通信方法を提供します。
  2. データグラム ソケット (UDP ソケット): UDP プロトコルに基づいて、コネクションレスで信頼性の低い通信方法を提供します。これは、データ量が少なく、応答が速く、リアルタイム要件が高いアプリケーションに適しています。
  3. Raw Socket (Raw Socket): ネットワーク プロトコルへの低レベルのアクセスを提供し、特定のネットワーク プロトコルと機能の実装に適しています。

2.2-方法: ソケット通信の実装手順

ソケット通信を実装する手順は通常次のとおりです。

  1. ソケットの作成:socket() 関数を使用してソケットを作成し、通信プロトコル、アドレス ファミリ、ソケット タイプなどのパラメーターを指定します。ソケットが正常に作成されると、システムは一意のソケット記述子 (ソケット ファイル記述子) をソケットに割り当てます。
  2. ソケットのバインド:bind() 関数を使用してソケットをローカル アドレスとポートにバインドし、クライアントがソケットに接続できるようにします。Socket をバインドするときは、通信プロトコル、アドレス ファミリ、ローカル アドレスなどのパラメータを指定する必要があります。
  3. リスニング ソケット: listen() 関数を使用して、ソケットをリスニング状態に設定し、クライアントからの接続要求を待ちます。Socket をリッスンするときは、最大接続数などのパラメーターを指定する必要があります。
  4. 接続を受け入れる: accept() 関数を使用してクライアントの接続要求を受け入れ、クライアントと通信するための新しいソケットを作成します。接続を受け入れるときは、リッスンするソケットやクライアント アドレスなどのパラメーターを指定する必要があります。
  5. データの送受信: send() 関数を使用してピアにデータを送信し、recv() 関数を使用してピアによって送信されたデータを受信します。データを送受信する際には、通信ソケット、送受信バッファ、データ長などのパラメータを指定する必要があります。
  6. ソケットを閉じる: close() 関数を使用してソケットを閉じ、システム リソースを解放します。以上がTCPプロトコルに基づくソケット通信の実装手順です。

UDPプロトコルによるSocket通信であれば、コネクションを確立する必要はなく、データの送受信時に相手のアドレスとポートを指定するだけで済みます。

2.3-方法: ソケット書き込みプロセス

TCP のソケット プログラミング:
ここに画像の説明を挿入

ソケット書き込みプロセス

  • サーバーとクライアントが初期化されsocket、ファイル記述子が取得されます。
  • サーバーは、bindソケットを指定された IP アドレスとポートにバインドするために呼び出します。
  • サーバーは呼び出しlistenと監視を行います。
  • サーバーは呼び出しを行いaccept、クライアントが接続するのを待ちます。
  • connectサーバーのアドレスとポートへの接続リクエストを開始するためにクライアントによって呼び出されます。
  • サーバーは転送用のファイル記述子acceptを返します。socket
  • クライアントはデータの書き込みを呼び出しwrite、サーバーはreadデータの読み取りを呼び出します。
  • クライアントが切断すると、 が呼び出されclose、サーバーがreadデータを読み取ると、 が読み取られますEOF。データが処理された後、サーバーはclose接続が閉じられたことを示すために を呼び出します。

acceptここで、サーバーが を呼び出すと、接続が成功すると、接続を完了したソケットが返され、後でデータを送信するために使用されることに注意してください。

したがって、待機ソケットと実際にデータ送信に使用されるソケットは「2 つ」のソケットとなり、1 つは待機ソケット、もう 1 つは完了接続ソケットと呼ばれます。

接続が正常に確立されると、ファイル ストリームに何かを書き込むのと同じように、両者は読み取りおよび書き込み関数を通じてデータの読み取りと書き込みを開始します。

以下は、Linux での簡単なソケット プログラミングの例です。
Linux でのソケット デモ プログラム

3-Socket の主要な実装

この記事の議論と実装はすべて Linux 環境で行われます。

3.1-socket() 関数はソケットを作成します

Linux では、<sys/socket.h> ヘッダー ファイルのソケット() 関数を使用してソケットを作成します。プロトタイプは次のとおりです。

int socket(int af, int type, int protocol);

(1) af はアドレス ファミリ (Address Family)、つまり IP アドレスの種類で、一般的に使用されるのは AF_INET と AF_INET6 です。AF は「Address Family」の略で、INET は「Inetnet」の略です。AF_INET は IPv4 アドレス (127.0.0.1 など) を表し、AF_INET6 は IPv6 アドレス (1030::C9B4:FF12:48AA:1A2B など) を表します。

(注: 127.0.0.1 は特別な IP アドレスであり、本機のアドレスを示します)

(2) type はデータ送信方法/ソケットのタイプで、一般的に使用されるのは SOCK_STREAM (ストリーム形式ソケット/コネクション型ソケット) と SOCK_DGRAM (データグラム ソケット/コネクションレス ソケット) です。

(3)protocol は伝送プロトコルを示し、IPPROTO_TCP と IPPTOTO_UDP が一般的に使用され、それぞれ TCP 伝送プロトコルと UDP 伝送プロトコルを示します。

このチュートリアルでは IPv4 アドレスを使用し、パラメータ af の値は PF_INET です。SOCK_STREAM を使用してデータを送信する場合、これら 2 つの条件を満たす唯一のプロトコルは TCP であるため、socket() 関数は次のように呼び出すことができます。

int tcp_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  //IPPROTO_TCP表示TCP协议

このようなソケットは TCP ソケットと呼ばれます。

SOCK_DGRAM 送信メソッドが使用される場合、これら 2 つの条件を満たす唯一のプロトコルは UDP であるため、socket() 関数は次のように呼び出すことができます。

int udp_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);  //IPPROTO_UDP表示UDP协议

このようなソケットは UDP ソケットと呼ばれます。

上記の 2 つのケースでは、条件を満たすプロトコルは 1 つだけです。プロトコルの値を 0 に設定すると、以下に示すように、システムがどのプロトコルを使用するかを自動的に推測します。

int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);  //创建TCP套接字
int udp_socket = socket(AF_INET, SOCK_DGRAM, 0);  //创建UDP套接字

3.2-bind() connect() 関数

次の実装はすべて Linux 環境にあります

ソケットを作成し、ソケットのさまざまな属性を決定するには、socket() 関数を使用します。その後、サーバーは、bind() 関数を使用して、ソケットを特定の IP アドレスとポートにバインドします。この方法でのみ、 IP アドレスとポート データのみを処理のためにソケットに渡すことができます。同様に、クライアントも connect() 関数を使用して接続を確立する必要があります。

bind() 関数のプロトタイプは次のとおりです。

int bind(int sock, struct sockaddr *addr, socklen_t addrlen);  //Linux

sock はソケット ファイル記述子、addr は sockaddr 構造体変数のポインタ、addrlen は addr 変数のサイズで、sizeof() で計算できます。

sockaddr はさまざまなタイプの IP アドレスとポート番号を格納するために使用できる一般的な構造体であり、sockaddr_in は IPv4 アドレスを格納するために特別に使用される構造体です。IPv6 アドレスを格納するために使用される sockaddr_in6 もあります。

一般的な構造 sockaddr は使用するのが不便であるため、アドレスの種類ごとに異なる構造が定義されています。

sockaddr 構造体は次のように定義されます。

struct sockaddr{
    
    
    sa_family_t  sin_family;   //地址族(Address Family),也就是地址类型
    char         sa_data[14];  //IP地址和端口号
};

sockaddr の長さは 16 バイト (sin_family が 2 バイト、sa_data が 14 バイト) で、IP アドレスとポート番号を組み合わせてメンバー sa_data で表します。sa_data に値を割り当てるには、「127.0.0.1:80」のように、IP アドレスとポート番号を同時に指定する必要があります。残念ながら、この文字列を必要な形式に変換する関連関数はありません。 sockaddr 割り当て型の変数を割り当てるのは難しいため、代わりに sockaddr_in を使用してください。

2 つの構造体は同じ長さであり、型を強制するときにバイトが失われたり、余分なバイトが発生したりすることはありません。

IPv4 専用アドレス格納構造体 - sockaddr_in 構造体のメンバー変数は次のとおりです。

struct sockaddr_in{
    
        
    sa_family_t     sin_family;   //地址族(Address Family),也就是地址类型    
    uint16_t        sin_port;     //16位的端口号    
    struct in_addr  sin_addr;     //32位IP地址    
    char            sin_zero[8];  //不使用,一般用0填充
};

コード分​​析:

  1. sin_familyとsocket()の最初のパラメータの意味は同じであり、値も一貫している必要があります。

  2. sin_prot はポート番号です。uint16_t の長さは 2 バイトで、理論的にはポート番号の値の範囲は 0 ~ 65536 ですが、通常、0 ~ 1023 のポート番号はシステムによって特定のサービス プログラムに割り当てられます。 Web サービスは 80、FTP サービスのポート番号は 21 であるため、プログラムは 1024 ~ 65536 のポート番号を割り当てようとします。ポート番号は htons() 関数で変換する必要があります。

  3. sin_addr は、struct in_addr 構造体型の変数です。この構造体には、次のようにメンバーが 1 つだけ含まれています。

    struct in_addr{
          
              in_addr_t  s_addr;  //32位的IP地址
                  };
    

    in_addr_t はヘッダー ファイル <netinet/in.h> で定義されます。これは unsigned long と同等で、長さは 4 バイトです。つまり、s_addr は整数であり、IP アドレスは文字列であるため、変換には inet_addr() 関数が必要です。次に例を示します。

    unsigned long ip = inet_addr("127.0.0.1");
    printf("%ld\n", ip);
    

    実行結果:
    16777343

  4. sin_zero[8] は余分な 8 バイトですが、役に立たず、通常は memset() 関数を使用して 0 で埋められます。上記のコードでは、まず memset() を使用して構造体のすべてのバイトを 0 で埋め、次に最初の 3 つのメンバーに値を割り当てます。残りの sin_zero は当然 0 になります。

IPv6 専用アドレス格納構造体 - sockaddr_in6 構造体、そのメンバ変数は以下のとおりです。

struct sockaddr_in6 {
    
     
    sa_family_t sin6_family;  //(2)地址类型,取值为AF_INET6
    in_port_t sin6_port;  //(2)16位端口号
    uint32_t sin6_flowinfo;  //(4)IPv6流信息
    struct in6_addr sin6_addr;  //(4)具体的IPv6地址
    uint32_t sin6_scope_id;  //(4)接口范围ID
};

connect() 関数は接続を確立するために使用され、そのプロトタイプは次のとおりです。

int connect(int sock, struct sockaddr *serv_addr, socklen_t addrlen); 

各パラメータの説明はbind()の説明と同じで、sockはソケットファイル記述子、addrはsockaddr構造体変数のポインタ、addrlenはaddr変数のサイズで、sizeof()で計算できます。

3.3-listen() accept() 関数

サーバー側プログラムの場合、bind() を使用してソケットをバインドした後、listen() 関数を使用してソケットをパッシブ リスニング状態にし、accept() 関数を呼び出してクライアントの要求に応答する必要があります。いつでもリクエストしてください。

listen() 関数

listen 関数のプロトタイプは次のとおりです。

int listen(int sock, int backlog);  //Linux

sock は listen 状態に入る必要があるソケットであり、backlog は要求キューの最大長です。

いわゆるパッシブ監視とは、クライアント要求がない場合、ソケットは「スリープ」状態にあり、クライアント要求を受信した場合にのみ、ソケットが要求に応答するために「ウェイクアップ」されることを意味します。

リクエストキュー

ソケットがクライアントリクエストを処理しているときに、新しいリクエストが入ってきた場合、ソケットはそれを処理できず、バッファに入れることしかできず、現在のリクエストが処理された後にバッファから読み取って処理します。新しいリクエストが引き続き受信される場合、それらはバッファがいっぱいになるまで順番にバッファのキューに入れられます。このバッファをリクエストキュー(Request Queue)と呼びます。

バッファの長さ (保存できるクライアント要求の数) は、listen() 関数の backlog パラメータで指定できます。

初期の Linux カーネルのバックログには、未処理のキュー サイズである SYN キュー サイズがあります。

Linux カーネル 2.2 以降では、バックログが受け入れキュー、つまり接続の確立を完了したキューの長さになるため、現在ではバックログが受け入れキューであると考えるのが一般的です。

ただし、上限はカーネル パラメーター somaxconn のサイズ、つまり accpet キューの長さ = min(backlog, somaxconn) です。

backlog の値が SOMAXCONN に設定されている場合、システムはリクエスト キューの長さを決定します。この値は一般に比較的大きく、おそらく数百以上になります。

リクエスト キューがいっぱいになると、新しいリクエストは受け付けられなくなり、Linux の場合、クライアントは ECONNREFUSED エラーを受け取ります。

accept() 関数

ソケットが待機状態にある場合、クライアント要求は accept() 関数を通じて受信できます。そのプロトタイプは次のとおりです。

int accept(int sock, struct sockaddr *addr, socklen_t *addrlen);  //Linux

そのパラメータは listen() および connect() のパラメータと同じです。sock はサーバーソケット、addr は sockaddr_in 構造体変数、addrlen はパラメータ addr の長さで、sizeof() で取得できます。

注: accept() はクライアントと通信するための新しいソケットを返し、addr はクライアントの IP アドレスとポート番号を保存し、sock はサーバーのソケットです。区別に注意してください。後でクライアントと通信するときは、元のサーバー側ソケットの代わりに、この新しく生成されたソケットを使用します。

説明する必要があるのは、 listen() はソケットを listen 状態にするだけであり、実際にはクライアント要求を受信しないということです。listen() の背後にあるコードは、accept() に遭遇するまで実行を続けます。accept() は、新しいリクエストが到着するまでプログラムの実行をブロックします (次のコードは実行できません)。

3.4-write()/read() 関数

Linuxでのデータ受信と送信

Linux ではソケット ファイルと通常のファイルが区別されないため、ソケットにデータを書き込むには write() を使用し、ソケットからデータを読み取るには read() を使用します。

2 台のコンピュータ間の通信は、2 つのソケット間の通信と同等です。サーバー側では、write() を使用してソケットにデータを書き込み、クライアントはそれを受信し、次に read() を使用してソケットから読み取ります。単語が読み上げられると、コミュニケーションが完了します。

write() のプロトタイプは次のとおりです。

ssize_t write(int fd, const void *buf, size_t nbytes);

fd は書き込まれるファイルの記述子、buf は書き込まれるデータのバッファ アドレス、nbytes は書き込まれるデータのバイト数です。

size_t は、typedef によって宣言された unsigned int 型であり、ssize_t は、signed を表すために「size_t」の前に「s」を追加します。つまり、ssize_t は、typedef によって宣言された signed int 型です。

write() 関数関数: write() 関数は、バッファ buf 内の nbytes バイトをファイル fd に書き込み、成功した場合は書き込まれたバイト数を返し、失敗した場合は -1 を返します。

read() のプロトタイプは次のとおりです。

ssize_t read(int fd, void *buf, size_t nbytes);

fd は読み取るファイルの記述子、buf は受信するデータのバッファーアドレス、nbytes は読み取るデータのバイト数です。

read() 関数関数: read() 関数は fd ファイルから nbytes バイトを読み取り、バッファ buf に保存します。成功した場合は、読み取ったバイト数を返します (ただし、ファイルの終わりに達すると 0 を返します)。失敗した場合は -1 を返します。

4ソケットの基本原理

ソケット通信の主要な基盤テクノロジーには、主に次の点が含まれます。

OSI モデル(Open Systems Interconnection Model): これは、ネットワーク通信システムを記述するために使用される概念モデルです。ネットワーク通信を物理層からアプリケーション層まで 7 つの層に分割します。ソケット通信には主にトランスポート層 (TCP/UDP) とアプリケーション層が含まれます。
ここに画像の説明を挿入

TCP/IP プロトコル ファミリ:ソケット通信は主に TCP/IP プロトコル ファミリに依存します。TCP/IP プロトコル スイートには、IP (インターネット プロトコル、ネットワーク層プロトコル)、TCP (伝送制御プロトコル、トランスポート層プロトコル)、UDP (ユーザー データグラム プロトコル、トランスポート層プロトコル) など、相互に関連するネットワーク プロトコルのセットが含まれています。ソケット通信では、データ送信に TCP または UDP プロトコルが使用されます。

TCP 接続が確立されるときの 3 ウェイ ハンドシェイク プロセス:

TCP の 3 ウェイ ハンドシェイク プロセスとは何ですか?

TCP 接続が切断されたときの 4 つのウェーブ プロセス:

TCP 4 方向ウェーブのプロセスは何ですか?

ソケット:ソケットは、ネットワーク通信用のプログラミング インターフェイスです。これにより、アプリケーションはネットワーク層 (IP など) およびトランスポート層 (TCP または UDP など) プロトコルを介して通信できるようになります。ソケットは、異なるデバイス間でデータを転送するための共通の方法を提供し、ネットワーク プログラミングをより簡単かつ理解しやすくします。

ストリーム ソケット (ストリーム ソケット) は「接続指向ソケット」とも呼ばれ、コードでは SOCK_STREAM で表されます。

SOCK_STREAM は、信頼性の高い双方向の通信データ ストリームであり、データはエラーなく別のコンピュータに到達でき、破損または紛失した場合には再送信できます。

SOCK_STREAM には次の特性があります。

  • 送信中にデータが消えることはありません。
  • データは順番に送信されます。
  • データの送受信は同期しません (一部のチュートリアルでは「データ境界は存在しない」とも述べられています)。

「データ送信プロセスは消えません」 「データは順番に送信されます」

SOCK_STREAM はベルトコンベアに例えると、ベルトコンベア自体に問題がない限り(ネットワークが切断されない限り)、データが失われることはありませんが、後から送信されたデータが先に届くこともありません。となり、先に送信したデータが遅れて到着することはなく、確実にデータが順番に配信されます。

ストリーム形式のソケットが高品質なデータ伝送を実現できるのは、TCPプロトコルを使用しているため、データがエラーなく順番に届くように制御されます。

「データの送受信が同期していない」ことをどのように理解すればよいですか?

ベルトコンベアがグレープフルーツを配送すると仮定すると、荷受人はグレープフルーツを 20 個集めて袋に詰める必要がありますが、グレープフルーツは異なる位置に配置されているため、ベルトコンベアはこれらのグレープフルーツをバッチで送信する可能性があります。第一弾は5本、第二弾は10本、第三弾は5本です。受信機はベルトコンベアの動きに合わせる必要がなく、ベルトコンベアが何バッチを送るかは気にせず、すべてのバッチを袋詰めする必要もなく、20 個のグレープフルーツを集めて袋詰めするだけで済みます。

ストリーム形式のソケット内にはバッファ(つまり文字配列)があり、ソケットを通じて送信されたデータはこのバッファに保存されます。受信側は、データを受信して​​すぐにデータを読み出す必要はなく、バッファの容量を超えない限り、バッファがいっぱいになってから一度読み出してもよいし、複数回読み出してもよい。

つまり、データが何度送信されても​​、受信側は必要に応じてデータを読み取るだけでよく、データが到着したらすぐに読み取る必要はありません。送信側にも独自のリズムがあり、受信側にも独自のリズムがあり、それらは一定ではありません。

ストリーム形式ソケットの実際の適用シナリオは何ですか? ブラウザで使用される http プロトコルは接続指向のソケットに基づいています。これは、データが正しいことが保証される必要があり、そうでないとロードされた HTML が解析されないためです。

データグラム ソケット (データグラム ソケット) は「コネクションレス ソケット」とも呼ばれ、コードでは SOCK_DGRAM で表されます。

コンピュータはデータを送信するだけでデータの確認は行わないため、送信中にデータが破損したり、他のコンピュータに届かなかったりした場合、修復する方法がありません。つまり、データが間違っている場合は、間違っているので再送信することはできません。データグラムソケットは検証作業が少ないため、伝送効率の点でストリーム形式のソケットよりも効率的です。

SOCK_DGRAM は、次のような特徴を持つ高速バイクにたとえられます。

  • 転送順序よりも高速転送を重視します。
  • 送信されたデータが失われたり破損したりする可能性があります。
  • 各転送のデータ サイズを制限します。
  • データの送受信は同期です (一部のチュートリアルでは「データ境界がある」とも呼ばれています)。

ご存知のとおり、速達業界ではスピードが命です。バイクで同じ場所に送る 2 つの荷物の注文を保証する必要はありません。できるだけ早くお客様に届けられる限り、悪天候や人為的ミスにより速達便が遅延または紛失する可能性があります。 。このように破損または紛失の危険性があり、梱包サイズには一定の制限があります。したがって、大量の荷物を配送したい場合は、配送を分散する必要があります。

さらに、2 台のバイクで 2 つの荷物を送信すると、受信側も 2 回受信する必要があるため、「データの送受信は同期」されます。

つまり、データグラム ソケットは信頼性が低く、速度の点で順序が乱れた配信ソケットです。

データグラムソケットもルーティングに IP プロトコルを使用しますが、TCP プロトコルは使用せず、UDP プロトコル (ユーザー データグラム プロトコル、ユーザー データグラム プロトコル) を使用します。

QQ ビデオ チャットおよび音声チャットでは、通信の効率を第一に確保し、遅延を最小限に抑える必要があり、データの正確性は二の次であるため、SOCK_DGRAM を使用してデータを送信します。通常の分析であれば、せいぜいノイズやノイズが通信品質に大きな影響を与えることはありません。

注: SOCK_DGRAM は想像されているほど悪くはなく、データが頻繁に失われることはなく、データ エラーが発生する可能性はわずかです。

IP、MAC、ポート番号 - ネットワーク通信におけるアイデンティティ情報を確認する 3 つの要素

IP アドレス: IP アドレスは Internet Protocol Address の略称で、「インターネット プロトコル アドレス」と訳されます。IP アドレスは、ネットワーク デバイスを識別するために使用される数値アドレスです。IPv4 (インターネット プロトコル バージョン 4) では、IP アドレスは 4 バイトで構成されます (例: 192.168.1.1)。IPv6 (インターネット プロトコル バージョン 6) では、IP アドレスは 2001:0db8:85a3:0000:0000:8a2e:0370:7334 のように、16 桁の 16 進数の 8 つのグループで構成されます。インターネット上で通信を行う場合、相手のIPアドレスを知る必要があります。実は、データパケットにはすでにIPアドレスが付加されており、ルーターにデータパケットを送信すると、ルーターはそのIPアドレスから相手の位置を割り出し、データ転送を完了します。

MAC アドレス: MAC アドレスは、Media Access Control Address の略語で、文字通り「メディア アクセス コントロール アドレス」と訳され、LAN アドレス (LAN アドレス)、イーサネット アドレス (イーサネット アドレス)、または物理アドレス (物理アドレス) とも呼ばれます。

実際には、LAN は独立した IP を持つことがよくあります。つまり、IP アドレスは LAN 上にのみ存在し、特定のコンピュータには存在しません。私に何ができる?このようなコミュニケーション方法はありません。

実際、コンピュータを真に一意に識別できるのは MAC アドレスであり、各ネットワーク カードの MAC アドレスは世界で一意です。コンピュータが工場から出荷された時点で、MAC アドレスはネットワーク カードにハードコーディングされています (もちろん、「高度なスキル」を使用して変更することもできます)。LAN 内のルーター/スイッチは、各コンピューターの MAC アドレスを追跡します。

データ パケットには相手の IP アドレスに加えて相手の MAC アドレスも伴い、データ パケットが LAN に到達すると、ルーター/スイッチはその MAC アドレスに基づいて対応するコンピュータを見つけます。データパケットを転送し、データパケットを転送することでデータ転送が完了します。

ポート:ポート番号は、ネットワーク サービスまたはアプリケーションを識別するために使用される番号です。

IPアドレスとMACアドレスがあれば、目的のコンピュータを見つけることはできても、通信することはできません。コンピュータは、Web サービス (Web サイト)、FTP サービス (ファイル転送サービス)、SMTP サービス (メールボックス サービス) などの複数のネットワーク サービスを同時に提供できますが、コンピュータが提供できるのは IP アドレスと MAC アドレスのみです。データ パケットを正しく受信しますが、処理のためにデータ パケットをどのネットワーク プログラムに渡すべきかがわからないため、通信は失敗します。

異なるネットワーク プログラムを区別するために、コンピュータは各ネットワーク プログラムに固有のポート番号 (ポート番号) を割り当てます。ポート番号の範囲は 0 ~ 65535 で、通常 0 ~ 1023 はシステムまたは既知のサービス (HTTP、FTP など) 用に予約されています。たとえば、Web サービスのポート番号は 80、FTP サービスのポート番号は 21、SMTP サービスのポート番号は 25 です。

ポート (Port) は仮想的で論理的な概念です。ポートは、データが出入りするドアとして理解でき、各ドアには異なる番号 (ポート番号) が割り当てられます。以下に示すように:

ここに画像の説明を挿入

5ソケットのメリットとデメリット

ソケット通信の利点:

  1. ネットワーク通信プロトコルの柔軟性: ソケットは、TCP、UDP、HTTP などのさまざまなネットワーク通信プロトコルをサポートできます。ソケットは、強力な汎用性と柔軟性を備えており、さまざまなネットワーク アプリケーション要件を満たすことができます。

  2. データ伝送の信頼性: ソケットは接続指向の通信方式を提供し、データ伝送の信頼性と整合性を確保し、データの損失、重複、損傷などの問題を回避できます。

  3. システム リソースの効率的な利用: ソケットはマルチスレッドおよびマルチプロセス テクノロジーを使用して、複数のクライアント要求の同時処理を実現し、システム リソースを最大限に活用し、通信効率とスループットを向上させることができます。

  4. プログラミングの柔軟性: ソケットはさまざまなプログラミング言語とツールを使用して開発でき、プログラミングの柔軟性が高く、特定のニーズに応じてカスタマイズできます。

ソケット通信のデメリット:

1. ネットワーク通信のセキュリティ問題: ソケット通信には、データの盗聴、改ざん、偽造などのネットワークセキュリティの問題があります。通信のセキュリティを確保するには、何らかのセキュリティ対策が必要です。

2. ネットワーク環境の不安定性:ソケット通信は、ネットワーク遅延、パケットロス、輻輳などのネットワーク環境の影響を受け、通信効率や信頼性に影響を与えます。

3. システム リソースの占有率が高い: ソケット通信は、メモリ、CPU などの特定のシステム リソースを占有する必要があります。多数のクライアント要求が同時に処理されると、大量のシステム リソースが占有される可能性があり、その結果、過剰なシステム負荷がかかっています。

6ソケットチューニング

6.1-ソケット通信のエラー処理

Socket通信を行う際には、ネットワーク例外、接続中断、タイムアウトなどの様々なエラーが発生する可能性があり、プログラムの安定性と信頼性を確保するためには、Socket通信のエラーに対処する必要があります。以下に続きます:

  1. エラー検出:Socket通信を行う場合、各Socketオペレーションの戻り値を検出する必要があり、戻り値が0未満の場合はエラーが発生したことを意味します。

  2. エラーの処理: 発生したエラーについては、エラー メッセージの出力、ソケット接続の終了、ソケット操作の再試行など、対応する処理が必要です。

  3. 接続の復元: ソケット接続が中断された場合、再接続、接続の再試行などの接続回復操作を実行する必要があります。

  4. タイムアウト処理: ソケット操作がタイムアウトした場合、ソケット操作の再実行、ソケット接続のクローズなど、対応する処理を実行する必要があります。

  5. 例外処理メカニズムを使用する: ソケット通信を実行するとき、try-catch ステートメントを使用して例外をキャッチし、それに応じて処理するなど、例外処理メカニズムを使用して異常な状況を処理できます。

  6. ログ: ソケット通信中にログを記録してエラーを追跡し、プログラムをデバッグすることで、問題を迅速に特定して解決できます。

6.2 - ソケット通信の一般的な最適化方法

ソケット通信の一般的な最適化方法には、次の側面が含まれます。

  1. ノンブロッキング ソケットを使用する: ノンブロッキング ソケットを使用すると、ソケットがデータを返すのを待機する際のプログラムのブロックを回避できるため、プログラムの同時パフォーマンスと応答速度が向上します。

  2. マルチスレッドまたはマルチプロセスを使用する: マルチスレッドまたはマルチプロセスを使用すると、Socket 通信を異なるスレッドまたはプロセスに割り当てて処理できるため、プログラムの同時実行パフォーマンスと応答速度が向上します。

  3. 非同期 I/O を使用する: 非同期 I/O は、ソケットがデータを返すのを待機している間に他の操作を実行できるため、プログラムの同時パフォーマンスと応答速度が向上します。

  4. TCP パラメータの調整: TCP パラメータを調整することで、TCP ウィンドウ サイズやタイムアウト時間などの調整など、ソケット通信のパフォーマンスを向上させることができます。また、TCP の 3 ウェイ ハンドシェイク、4 ウェイ ハンドシェイク、そしてデータ送信。(参考:TCPを最適化するには?

  5. キャッシュ技術を使用する: キャッシュ技術を使用すると、Socket 通信でのデータ送信数が削減され、プログラムのスループットと応答速度が向上します。

  6. ゼロ コピー テクノロジを使用する: ゼロ コピー テクノロジを使用すると、データ送信中のデータ コピーの数を減らすことができるため、CPU とメモリの消費量が削減され、プログラムのパフォーマンスとスループットが向上します。

  7. ソケット接続の確立と終了の回数を減らす: ソケット接続の確立と終了には、特定のリソースと時間が消費されます。ソケット接続の確立と終了を減らすと、プログラムのパフォーマンスと安定性が向上します。

  8. データ転送形式の最適化: データ転送形式を最適化すると、データ転送量が削減され、プログラムのスループットと応答速度が向上します。

ソケット通信の最適化は、特定のアプリケーション シナリオと要件に応じて調整する必要があり、最適なパフォーマンスと安定性を実現するには、ネットワーク帯域幅、データ送信量、ネットワーク遅延、システム リソースなどの要素を総合的に考慮する必要があります。

7 ソケットの該当するシナリオ

ソケット通信は、異なるデバイス間のデータ送信を可能にするネットワークベースの通信方法です。さまざまなビジネス シナリオや技術的なシナリオに適しています。いくつかの典型的なアプリケーションを以下に示します。

ビジネスシーン

  1. インスタント メッセージング: チャット アプリケーション、オンライン カスタマー サービス、およびテキスト、音声、画像などのマルチメディア情報のリアルタイムかつ効率的な送信が必要なその他のシナリオ。
  2. リアルタイム監視: IoT デバイス、産業用センサー、および監視データをリアルタイムで収集および送信する必要があるその他のシナリオ。
  3. リモート コントロール: リモート デスクトップ コントロール、ドローン リモート コントロール、および指示やステータス情報のリアルタイム送信が必要なその他のシナリオ。
  4. ファイル転送: FTP やその他のソケットベースのファイル転送プロトコルなど、大規模なファイル転送をサポートするアプリケーション。

テクニカルシーン

  1. TCP 通信: 伝送制御プロトコル (TCP) は、コネクション指向で信頼性の高いバイトストリームベースの通信プロトコルです。TCP ソケット通信は、HTTP、SMTP、その他のプロトコルなど、信頼性の高いデータ送信が必要なシナリオで広く使用されています。
  2. UDP 通信: ユーザー データグラム プロトコル (UDP) は、コネクションレスで信頼性の低いデータグラム ベースの通信プロトコルです。UDP ソケット通信は、リアルタイムのオーディオおよびビデオ通信、オンライン ゲームなど、リアルタイム要件が高く、一部のデータの損失が許容されるシナリオに適しています。
  3. Unix ドメイン ソケット通信: Unix ドメイン ソケットは、同一ホスト上のプロセス間通信 (IPC) に使用され、TCP/UDP と比較して効率的な通信方式を提供します。
  4. Web ソケット通信: Web ソケット プロトコルは、単一の TCP 接続を介した全二重通信のためのプロトコルです。オンライン チャット、リアルタイム データ プッシュなど、リアルタイムの双方向データ送信を必要とする Web アプリケーション シナリオに適しています。
  5. 暗号化通信: 安全なデータ送信が必要なシナリオでは、SSL/TLS を使用して、HTTPS、IMAPS、その他のプロトコルなどのソケット通信を暗号化できます。
  6. 多重化と負荷分散: ソケット通信を使用して多重化 (多重化) と負荷分散を実現し、ネットワーク リソースの使用率とサービスの可用性を向上させます。

8- 参考文献

『TCP/IP 詳細解説 第1巻:プロトコル』

小林coding

C言語中国語サイト - ソケット通信

9ソケット高周波問題

1. ソケット通信とは何ですか?またその機能は何ですか?

2. ソケット通信の 2 つのプロトコルは何ですか? それらの違いは何ですか?

3. ソケット通信の 5 つの基本操作とは何ですか?

4. ソケット通信におけるブロッキング モードとノンブロッキング モードの違いは何ですか?

5. ソケット通信における TCP プロトコルと UDP プロトコルの違いは何ですか? どのようなシナリオで使用する必要がありますか?

6. サーバーとクライアントとは何ですか?また、ソケット通信におけるそれらの役割は何ですか?

7. ソケット通信エラー時の対処方法は?

8. ソケット通信におけるデータ送信方式にはどのようなものがありますか?メリット・デメリットは何ですか?

10. ソケット通信のパフォーマンスを最適化するには? 一般的な最適化方法は何ですか?

おすすめ

転載: blog.csdn.net/XieHYBlog/article/details/129940418