検索
ホームページバックエンド開発PHPチュートリアルソケットソケット(TCP、UDP)の詳しい説明

LInux を学習する場合、ネットワーク プログラミング ソケットは基礎であり、初心者にとっては学習の難しい点です。この記事を通じて、読者は図と著者のコードを通じて IP アドレス、ポート番号、TCP、UDP の概念、ソケット API を完全に理解できます。実装のアイデア、使用法、クライアント/サーバー通信のシミュレートなど

  • マーク: ブログのコード実装を読むのに 18 分かかりました<br>
  • ソケットソケット(TCP、UDP)の詳しい説明


article 重要なポイント:
  • #IP アドレス、ポート番号...

  • ソケット API

  • UDP クライアントの実装 クライアント/サーバー


    ソケットは、ネットワーク プログラミングにおける通信メカニズムであり、TCP/IP をサポートするネットワーク通信の基本操作単位です。これは、異なるホスト上のプロセス間の双方向通信のためのエンドポイントです。簡単に言うと、通信する 2 つの当事者間の合意です。ソケット内の関連する関数は、通信プロセスを完了するために使用されます。
前に紹介したように、ローカル プロセス間通信 (IPC) にはさまざまな方法があります。一般的な方法は次の点にまとめられています。

 1、管道(包括无名管道和命名管道);
 2、消息队列;
 3、信号量;
 4、共享存储。
 5、……( Socket和Streams支持不同主机上的两个进程IPC)。
ネットワーク層の通信プロセスを理解する:

ソケットソケット(TCP、UDP)の詳しい説明

IP との最初の知り合い:
(IP は: インターネット プロトコル IP)

ソケットソケット(TCP、UDP)の詳しい説明

通信中、IP は送信元 IP と宛先 IP に分けられます

速達の送信の比較: ネットワーク通信は速達の送信と受信に相当します IP は受信者/送信者のアドレスです。アドレスがわかれば十分です。だけでは不十分です。送信者が誰であるかを知る必要もあります。誰ですか?これはネットワークのポート番号の概念と比較され、ポート番号はプロセスを識別し、分析のために現在のデータがどのプログラムに渡されるかをオペレーティング システムに伝えます。


ポート番号:
ポート番号 (ポート) は、トランスポート層プロトコルの内容です。

  • ポート番号は 2 バイトの 16 ビット整数です。

  • ポート番号は、プロセスを識別し、動作しているプロセスを通知するために使用されます。現在のどのプログラムにデータを分析のために引き渡す必要があるか、

  • #IP アドレスとポート番号により、ネットワーク上の特定のホストの特定のプロセスを識別できます。
  • # #ポート番号は 1 つのプロセスによってのみ占有できます。

  • ポート番号とプロセス:

コンセプト
  • プロセスには独自のpid 識別、ポート番号でプロセスを識別することもできます。
1 つのプロセスを複数のポート番号にバインドできますが、1 つのポート番号を複数のプロセスにバインドすることはできません。

送信元ポート番号と宛先ポート番号
  • トランスポート層プロトコル (TCP/IP) のデータ セグメント送信元ポート番号と宛先ポート番号と呼ばれる 2 つのポート番号は、「データが誰のものか? 誰に送信されるか?」を表します。
TCP:

(TCP ) 送信制御プロトコル、接続指向。これは、信頼性の高いデータ送信を提供する一般的なプロトコルです。
#トランスポート層プロトコル

  • 接続済み

  • 信頼性の高い伝送

  • #バイト ストリーム指向
  • UDP:
  • (UDP) ユーザー データグラム プロトコルは、コネクションレス指向のプロトコルです。このプロトコルを使用する場合、2 つのアプリケーションが最初に接続を確立する必要はありません。 UDP プロトコルにはエラー回復機能がなく、データの再送信もできないため、このプロトコルのデータ送信セキュリティは不十分です。

#トランスポート層プロトコル

接続なし
  • 信頼性の低い伝送
  • データグラム指向
  • ネットワークバイトオーダー:

# 定義方法ネットワークデータフローのアドレス?

ソケットソケット(TCP、UDP)の詳しい説明

  • 実は、この問題は、C 言語のビッグ エンディアンとスモール エンディアンの問題であり、非常に理解しやすいです。
送信機はメモリ アドレスの低位から高位の順に送信し、

ソケットソケット(TCP、UDP)の詳しい説明

#受信ホストはメモリ アドレスの低位から高位の順に保存します;

  • TCP/IP 規制: ネットワーク データ フローではビッグ エンディアン バイト オーダー、つまり

    アドレス上位バイト
  • ;
  • ホストがビッグ エンディアン マシンであってもリトル エンディアン マシンであっても、TCP/IP 規則に従う必要があります;
  • 送信側がリトル エンディアンの場合は、データを送信する前にビッグエンディアンに変換します。

socket API:
//创建socket文件描述符  (TCP/UDP,客户端+服务器)

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

参数1(domain): 选择创建的套接字所用的协议族; <br>  AF_INET : IPv4协议; <br>  AF_INET6: IPv6协议; <br>  AF_LOCAL: Unix域协议; <br>  AF_ROUTE:路由套接口; <br>  AF_KEY :密钥套接口。 <br>参数2(type):指定套接口类型,所选类型有: <br>  SOCK_STREAM:字节流套接字; <br>  SOCK_DGRAM : 数据报套接字; <br>  SOCK_RAW : 原始套接口。 <br>  procotol: 使用的特定协议,一般使用默认协议(NULL)。

//绑定端口号  (TCP/IP,服务器)
int bind(int socket, const struct sockaddr *address, socklen_t address_len);

参数1(socket) : 是由socket()调用返回的并且未作连接的套接字描述符(套接字号)。 <br>参数2(address):指向特定协议的地址指针。 <br>参数3(address_len):上面地址结构的长度。 <br>返回值:没有错误,bind()返回0,否则SOCKET_ERROR。

//开始监听socket  (TCP,服务器)
int listen(int socket, int backlog);

参数1(sockfd):是由socket()调用返回的并且未作连接的套接字描述符(套接字号)。 <br>参数2(backlog):所监听的端口队列大小。

//接受请求  (TCP,服务器)
int accept(int socket, struct sockaddr* address, socklen_t* address_len);

参数1(socket) : 是由socket()调用返回的并且未作连接的套接字描述符(套接字号)。 <br>参数2(address):指向特定协议的地址指针。 <br>参数3(addrlen):上面地址结构的长度。 <br>返回值:没有错误,bind()返回0,否则SOCKET_ERROR。

//建立连接  (TCP,客户端)
int connect(int sockfd, const struct struct sockaddr *addr, aocklen_t addrlen);
//关闭套接字
int close(int fd);

参数(fd):是由socket()调用返回的并且未作连接的套接字描述符(套接字号)。

socket API是一层抽象的网络编程接口,适用于各种底层网络协议,如IPv4,IPv6,……

简单的TCP网络程序:
  • TCP客户—服务器程序的执行流程图:

ソケットソケット(TCP、UDP)の詳しい説明

服务器代码:

#include<iostream>
#include<unistd.h>
#include<stdio.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
using namespace std;

#define SERVER_PORT  5050               //端口号
#define SERVER_IP    "192.168.3.254"    //服务器ip
#define QUEUE_SIZE   5                  //所监听端口队列大小

int main(int argc, char *argv[])
{
    //创建一个套接字,并检测是否创建成功
    int sockSer;                        
    sockSer = socket(AF_INET, SOCK_STREAM, 0);
    if(sockSer == -1){
        perror("socket");
    }

    //设置端口可以重用,可以多个客户端连接同一个端口,并检测是否设置成功
    int yes = 1;
    if(setsockopt(sockSer, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1){
        perror("setsockopt");
    }

    struct sockaddr_in addrSer,addrCli;        //创建一个记录地址信息的结构体
    addrSer.sin_family = AF_INET;              //所使用AF_INET协议族
    addrSer.sin_port = htons(SERVER_PORT);     //设置地址结构体中的端口号
    addrSer.sin_addr.s_addr = inet_addr(SERVER_IP);   //设置其中的服务器ip

    //将套接字地址与所创建的套接字号联系起来。并检测是否绑定成功
    socklen_t addrlen = sizeof(struct sockaddr);
    int res = bind(sockSer,(struct sockaddr*)&addrSer, addrlen);
    if(res == -1)
        perror("bind");

    listen(sockSer, QUEUE_SIZE);       //监听端口队列是否由连接请求,如果有就将该端口设置位可连接状态,等待服务器接收连接

    printf("Server Wait Client Accept......\n");
    //如果监听到有连接请求接受连接请求。并检测是否连接成功,成功返回0,否则返回-1
    int sockConn = accept(sockSer, (struct sockaddr*)&addrCli, &addrlen);
    if(sockConn == -1)
        perror("accept");
    else
    {
        printf("Server Accept Client OK.\n");
        printf("Client IP:> %s\n", inet_ntoa(addrCli.sin_addr));
        printf("Client Port:> %d\n",ntohs(addrCli.sin_port));
    }

    char sendbuf[256];         //申请一个发送缓存区
    char recvbuf[256];         //申请一个接收缓存区
    while(1)
    {
        printf("Ser:>");
        scanf("%s",sendbuf);
        if(strncmp(sendbuf,"quit",4) == 0)    //如果所要发送的数据为"quit",则直接退出。
            break;
        send(sockConn, sendbuf, strlen(sendbuf)+1, 0);   //发送数据
        recv(sockConn, recvbuf, 256, 0);    //接收客户端发送的数据
        printf("Cli:> %s\n",recvbuf);
    }

    close(sockSer);         //关闭套接字
    return 0;
}

客户端代码:

#include<iostream>
#include<unistd.h>
#include<stdio.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
using namespace std;

#define SERVER_PORT  5050
#define SERVER_IP    "192.168.3.254"

int main(int argc, char *argv[])
{
    //创建客户端套接字号,并检测是否创建成功
    int sockCli;
    sockCli = socket(AF_INET, SOCK_STREAM, 0);
    if(sockCli == -1)
        perror("socket");

    //创建一个地址信息结构体,并对其内容进行设置
    struct sockaddr_in addrSer;     
    addrSer.sin_family = AF_INET;         //使用AF_INET协议族
    addrSer.sin_port = htons(SERVER_PORT);  //设置端口号
    addrSer.sin_addr.s_addr = inet_addr(SERVER_IP);   //设置服务器ip

    bind(sockCli,(struct sockaddr*)&addrCli, sizeof(struct sockaddr));    //将套接字地址与所创建的套接字号联系起来

    //创建一个与服务器的连接,并检测连接是否成功
    socklen_t addrlen = sizeof(struct sockaddr);
    int res = connect(sockCli,(struct sockaddr*)&addrSer, addrlen);
    if(res == -1)
        perror("connect");
    else
        printf("Client Connect Server OK.\n");

    char sendbuf[256];     //申请一个发送数据缓存区
    char recvbuf[256];     //申请一个接收数据缓存区
    while(1)
    {
        recv(sockCli, recvbuf, 256, 0);    //接收来自服务器的数据
        printf("Ser:> %s\n",recvbuf);
        printf("Cli:>");
        scanf("%s",sendbuf);
        if(strncmp(sendbuf,"quit", 4) == 0)    //如果客户端发送的数据为"quit",则退出。
            break;
        send(sockCli, sendbuf, strlen(sendbuf)+1, 0);   //发送数据
    }
    close(sockCli);       //关闭套接字
    return 0;
}
简单的UDP网络程序:

ソケットソケット(TCP、UDP)の詳しい説明

  • 相对与TCP来说,UDP安全性差,面向无链接。所以UDP地实现少了连接与接收连接的操作。所以在收发数据时就不能再用send()和recvfrom()了,而是用sendto()和recvto()之名从哪收发数据。
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);

参数1(sockfd):是由socket()调用返回的并且未作连接的套接字描述符(套接字号) <br>参数2(buf):指向存有发送数据的缓冲区的指针 <br>参数3(len):缓冲区长度。 <br>  **参数4(flags):**flags的值或为0,或为其他

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);

参数1(sockfd):是由socket()调用返回的并且未作连接的套接字描述符(套接字号) <br>参数2(buf):指向存有接收数据的缓冲区的指针 <br>参数3(len):缓冲区长度 <br>  **参数4(flags):**flags的值或为0,或为其他

服务器端代码:

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

int main()
{
    //创建一个套接字,并检测是否创建成功
    int sockSer = socket(AF_INET, SOCK_DGRAM, 0);
    if(sockSer == -1)
        perror("socket");

    struct sockaddr_in addrSer;  //创建一个记录地址信息的结构体 
    addrSer.sin_family = AF_INET;    //使用AF_INET协议族 
    addrSer.sin_port = htons(5050);     //设置地址结构体中的端口号
    addrSer.sin_addr.s_addr = inet_addr("192.168.3.169");  //设置通信ip

    //将套接字地址与所创建的套接字号联系起来,并检测是否绑定成功
    socklen_t addrlen = sizeof(struct sockaddr);
    int res = bind(sockSer,(struct sockaddr*)&addrSer, addrlen);
    if(res == -1)
        perror("bind");

    char sendbuf[256];    //申请一个发送数据缓存区
    char recvbuf[256];    //申请一个接收数据缓存区
    struct sockaddr_in addrCli;
    while(1)
    {
        recvfrom(sockSer,recvbuf,256,0,(struct  sockaddr*)&addrCli, &addrlen);     //从指定地址接收客户端数据
        printf("Cli:>%s\n",recvbuf);

        printf("Ser:>");    
        scanf("%s",sendbuf);
        sendto(sockSer,sendbuf,strlen(sendbuf)+1,0,(struct sockaddr*)&addrCli, addrlen);    //向客户端发送数据
    }
    return 0;
}

客户端代码:

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

int main()
{
    //创建一个套接字,并检测是否创建成功
    int sockCli = socket(AF_INET, SOCK_DGRAM, 0);
    if(sockCli == -1){
        perror("socket");
    }

    addrSer.sin_family = AF_INET;    //使用AF_INET协议族 
    addrSer.sin_port = htons(5050);     //设置地址结构体中的端口号
    addrSer.sin_addr.s_addr = inet_addr("192.168.3.169");  //设置通信ip
    socklen_t addrlen = sizeof(struct sockaddr);


    char sendbuf[256];    //申请一个发送数据缓存区
    char recvbuf[256];    //申请一个接收数据缓存区

    while(1){
        //向客户端发送数据
        printf("Cli:>");
        scanf("%s",sendbuf);
        sendto(sockCli, sendbuf, strlen(sendbuf)+1, 0, (struct sockaddr*)&addrSer, addrlen);   
        接收来自客户端的数据
        recvfrom(sockCli, recvbuf, BUFFER_SIZE, 0, (struct sockaddr*)&addrSer, &addrlen);
        printf("Ser:>%s\n", recvbuf);

    }

    return 0;
}

ソケットソケット(TCP、UDP)の詳しい説明

<br>
【推荐课程:TCP/IP视频教程

以上がソケットソケット(TCP、UDP)の詳しい説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事はCSDNで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。
PHPセッションを失敗させる可能性のあるいくつかの一般的な問題は何ですか?PHPセッションを失敗させる可能性のあるいくつかの一般的な問題は何ですか?Apr 25, 2025 am 12:16 AM

PHPSESSIONの障害の理由には、構成エラー、Cookieの問題、セッションの有効期限が含まれます。 1。構成エラー:正しいセッションをチェックして設定します。save_path。 2.Cookieの問題:Cookieが正しく設定されていることを確認してください。 3.セッションの有効期限:セッションを調整してください。GC_MAXLIFETIME値はセッション時間を延長します。

PHPでセッション関連の問題をどのようにデバッグしますか?PHPでセッション関連の問題をどのようにデバッグしますか?Apr 25, 2025 am 12:12 AM

PHPでセッションの問題をデバッグする方法は次のとおりです。1。セッションが正しく開始されるかどうかを確認します。 2.セッションIDの配信を確認します。 3.セッションデータのストレージと読み取りを確認します。 4.サーバーの構成を確認します。セッションIDとデータを出力し、セッションファイルのコンテンツを表示するなど、セッション関連の問題を効果的に診断して解決できます。

session_start()が複数回呼び出されるとどうなりますか?session_start()が複数回呼び出されるとどうなりますか?Apr 25, 2025 am 12:06 AM

session_start()への複数の呼び出しにより、警告メッセージと可能なデータ上書きが行われます。 1)PHPは警告を発し、セッションが開始されたことを促します。 2)セッションデータの予期しない上書きを引き起こす可能性があります。 3)session_status()を使用してセッションステータスを確認して、繰り返しの呼び出しを避けます。

PHPでセッションのライフタイムをどのように構成しますか?PHPでセッションのライフタイムをどのように構成しますか?Apr 25, 2025 am 12:05 AM

PHPでのセッションライフサイクルの構成は、session.gc_maxlifetimeとsession.cookie_lifetimeを設定することで達成できます。 1)session.gc_maxlifetimeサーバー側のセッションデータのサバイバル時間を制御します。 0に設定すると、ブラウザが閉じているとCookieが期限切れになります。

セッションを保存するためにデータベースを使用することの利点は何ですか?セッションを保存するためにデータベースを使用することの利点は何ですか?Apr 24, 2025 am 12:16 AM

データベースストレージセッションを使用することの主な利点には、持続性、スケーラビリティ、セキュリティが含まれます。 1。永続性:サーバーが再起動しても、セッションデータは変更されないままになります。 2。スケーラビリティ:分散システムに適用され、セッションデータが複数のサーバー間で同期されるようにします。 3。セキュリティ:データベースは、機密情報を保護するための暗号化されたストレージを提供します。

PHPでカスタムセッション処理をどのように実装しますか?PHPでカスタムセッション処理をどのように実装しますか?Apr 24, 2025 am 12:16 AM

PHPでのカスタムセッション処理の実装は、SessionHandlerInterfaceインターフェイスを実装することで実行できます。具体的な手順には、次のものが含まれます。1)CussentsessionHandlerなどのSessionHandlerInterfaceを実装するクラスの作成。 2)セッションデータのライフサイクルとストレージ方法を定義するためのインターフェイス(オープン、クローズ、読み取り、書き込み、破壊、GCなど)の書き換え方法。 3)PHPスクリプトでカスタムセッションプロセッサを登録し、セッションを開始します。これにより、データをMySQLやRedisなどのメディアに保存して、パフォーマンス、セキュリティ、スケーラビリティを改善できます。

セッションIDとは何ですか?セッションIDとは何ですか?Apr 24, 2025 am 12:13 AM

SessionIDは、ユーザーセッションのステータスを追跡するためにWebアプリケーションで使用されるメカニズムです。 1.ユーザーとサーバー間の複数のインタラクション中にユーザーのID情報を維持するために使用されるランダムに生成された文字列です。 2。サーバーは、ユーザーの複数のリクエストでこれらの要求を識別および関連付けるのに役立つCookieまたはURLパラメーターを介してクライアントに生成および送信します。 3.生成は通常、ランダムアルゴリズムを使用して、一意性と予測不可能性を確保します。 4.実際の開発では、Redisなどのメモリ内データベースを使用してセッションデータを保存してパフォーマンスとセキュリティを改善できます。

ステートレス環境(APIなど)でセッションをどのように処理しますか?ステートレス環境(APIなど)でセッションをどのように処理しますか?Apr 24, 2025 am 12:12 AM

APIなどのステートレス環境でのセッションの管理は、JWTまたはCookieを使用して達成できます。 1。JWTは、無国籍とスケーラビリティに適していますが、ビッグデータに関してはサイズが大きいです。 2.cookiesはより伝統的で実装が簡単ですが、セキュリティを確保するために慎重に構成する必要があります。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強力な PHP 統合開発環境

SublimeText3 英語版

SublimeText3 英語版

推奨: Win バージョン、コードプロンプトをサポート!

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

WebStorm Mac版

WebStorm Mac版

便利なJavaScript開発ツール