C++ プロジェクト戦闘 - UDP サーバー

目次

TCP と UDP

C/S モデル UDP 

ブロードキャスト

マルチキャスト 

setsockopt の役割


TCP と UDP

        トランスポート層で使用される主なプロトコル モデルは 2 つあります。1 つは TCP プロトコルで、もう 1 つは UDP プロトコルです。TCP プロトコルはネットワーク通信で支配的な役割を果たし、ネットワーク通信の大部分は TCP プロトコルを使用してデータ伝送を完了します。しかし、UDP はネットワーク通信において不可欠な通信手段でもあります。

        TCP と比較すると、UDP 通信の形式はテキスト メッセージの送信に似ています。データ送信前に接続を確立して維持する必要はありません。データを取得することに集中してください。スリーウェイ ハンドシェイクのプロセスが省略され、通信速度が大幅に向上しますが、それに伴う通信の安定性と正確性は保証されません。したがって、UDP を「コネクションレスで信頼性の低いメッセージ配信」と呼びます。

        では、よく知られている TCP と比較して、UDP の長所と短所は何ですか? 接続を作成する必要がないため、UDP オーバーヘッドが小さく、データ転送速度が速く、リアルタイム性が強いです。ビデオ会議やテレビ会議など、高いリアルタイム性が要求されるコミュニケーションの場で主に使用されます。しかし、信頼性の低いデータ伝送も伴い、伝送データの精度、伝送シーケンス、およびフローを制御および保証することはできません。したがって、通常の状況では、UDP プロトコルを使用してデータを送信しますが、データの正確性を保証するために、アプリケーション層に補助検証プロトコルを追加して、UDP の欠点を補う必要があります。信頼性の高いデータ伝送の目的。

        TCP と同様に、UDP もバッファがいっぱいになった後にデータを受信すると、パケット損失が発生する可能性があります。TCP スライディング ウィンドウ メカニズムがないため、通常は次の 2 つの方法が使用されます。

        1) サーバー アプリケーション層は、データの送信速度を制御するフロー制御を設計します。

        2) setsockopt 関数を使用して、受信バッファーのサイズを変更します。

#include <sys/socket.h>
int setsockopt(int sockfd,int level,int optname,const void *optval,socklen_t optlen);
    int n = 220x1024;
    setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&n,sizeof(n));

C/S モデル UDP 

        UDP は接続を維持する必要がないため、プログラム ロジックは単純ですが、UDP プロトコルは信頼性が低く、通信の信頼性を確保するためのメカニズムをアプリケーション層で実装する必要があります。

コード例:
 

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


#define MAXLINE     80
#define SERV_PORT   8080

int main(void)
{

    int n,i;
    struct sockaddr_in servaddr,cliaddr;
    socklen_t cliaddr_len;
    int sockfd;
    char str[INET_ADDRSTRLEN];
    char buf[MAXLINE];

    sockfd = socket(AF_INET,SOCK_DGRAM,0);
    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);

    bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));

    while(1)
    {

        cliaddr_len = sizeof(cliaddr);
        n = recvfrom(sockfd,buf,MAXLINE,0,(struct sockaddr *)&cliaddr,&cliaddr_len);
        if(n == -1)
        {
            perror("recvfrom error");
        }
        printf("连接来自 %s 在端口 %d\n",
                inet_ntop(AF_INET,&cliaddr.sin_addr,str,sizeof(str)),ntohs(cliaddr.sin_port));
        
        for(i=0;i<n;++i)
        {
            buf[i] = toupper(buf[i]);
        }

        n = sendto(sockfd,buf,n,0,(struct sockaddr *)&cliaddr,sizeof(cliaddr));
        if(n == -1)
        {
            perror("sendto error");
        }
    }

    close(sockfd);


    return 0;
}
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <string.h>
#include <ctype.h>

#define MAXLINE     80
#define SERV_PORT   8080

int main(void)
{

    int n;
    struct sockaddr_in servaddr;
    char str[INET_ADDRSTRLEN];
    char buf[MAXLINE];
    int sockfd;

    sockfd = socket(AF_INET,SOCK_DGRAM,0);

    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERV_PORT);
    inet_pton(AF_INET,"127.0.0.1",&servaddr.sin_addr);

    while(fgets(buf,MAXLINE,stdin) != NULL)
    {
        n = sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&servaddr,sizeof(servaddr));
        if(n == -1)
        {
            perror("sendto error");
        }
        n = recvfrom(sockfd,buf,MAXLINE,0,NULL,0);
        if(n == -1)
        {
            perror("recvfrom error");
        }
        write(STDOUT_FILENO,buf,n);
    }

    close(sockfd);

    return 0;
}

ブロードキャスト

int setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,&flag,sizeof(flag)); //靴下の属性を変更

sockfd へのブロードキャスト権限を開く

マルチキャスト 

        マルチキャストは永続的または一時的です。マルチキャスト アドレスの中には、正式に割り当てられ、永続的なマルチキャスト グループと呼ばれるものがあります。永続的なマルチキャスト グループで変更されないのはその IP アドレスであり、グループ内のメンバーの構成は変更される可能性があります。永続的なマルチキャスト グループのメンバーは任意であり、0 であってもかまいません。永続的なマルチキャスト用に予約されていない IP マルチキャスト アドレスは、一時的なマルチキャスト グループで使用できます。

224.0.0.0 ~ 224.0.0.255 は予約済みマルチキャスト アドレス (永続アドレス) で、アドレス 224.0.0.0 は予約済みで割り当てられず、その他はルーティング プロトコルによって使用されます。

224.0.1.0~224.0.1.255はインターネット上で利用できる公開マルチキャストアドレスで、利用申請が必要です。

224.0.2.0 ~ 238.255.255.255 は、ユーザーが使用できるマルチキャスト アドレスです (一時的なアドレス、ネットワーク全体で有効)

239.0.0.0 ~ 239.255.255.255 は、特定のローカル範囲内でのみ有効なローカル管理マルチキャスト アドレスです。

ip adコマンドを使用して、ネットワーク カード番号の IP アドレスを表示できます。

コマンドを使用してネットワークカードを有効/無効にします sudo ifconfig etho up/down

if_nametoindex 関数コマンドを使用して、ネットワーク カードの名前に基づいてネットワーク カードのシリアル番号を取得します。

#include <net/if.h>

unsigned int if_nametoindex(const char *ifname);

コード例:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <unistd.h>
#include <arpa/inet.h>

#define  SERVER_PORT  8080
#define  CLIENT_PORT  9000
#define  MAXLINE      1500
#define  GROUP        "239.0.0.2"   //本地组播地址

/*
struct ip_mreqn
{
    struct in_addr imr_multiaddr;	组播组的IP
    struct in_addr imr_address;		本地IP
    int	imr_ifindex;			    网卡编号
};
*/

int main(void)
{

    int sockfd,i;
    struct sockaddr_in  serveraddr,clientaddr;
    struct ip_mreqn     group;
    char   buf[MAXLINE]  = "itcast\n";

    sockfd = socket(AF_INET,SOCK_DGRAM,0);
    
    bzero(&serveraddr,sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
    serveraddr.sin_port = htons(SERVER_PORT);

    bind(sockfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));

    //设置组地址
    inet_pton(AF_INET,GROUP,&group.imr_multiaddr);
    //本地任意 IP
    inet_pton(AF_INET,"0.0.0.0",&group.imr_address);
    //eth0
    group.imr_ifindex = if_nametoindex("eth0");
    setsockopt(sockfd,IPPROTO_IP,IP_MULTICAST_IF,&group,sizeof(group));

    //构造 client 地址和端口
    bzero(&clientaddr,sizeof(clientaddr));
    clientaddr.sin_family = AF_INET;
    inet_pton(AF_INET,GROUP,&clientaddr.sin_addr.s_addr);
    clientaddr.sin_port = htons(CLIENT_PORT);

    while(1)
    {
        sendto(sockfd,buf,strlen(buf),0,(struct sockaddr *)&clientaddr,sizeof(clientaddr));
        sleep(1);
    }

    close(sockfd);

    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/stat.h>

#define SERVER_PORT     8080
#define MAXLINE         4096
#define CLIENT_PORT     9000
#define  GROUP        "239.0.0.2"   //本地组播地址

int main()
{

    struct sockaddr_in serveraddr,localaddr;
    int confd;
    ssize_t len;
    char buf[MAXLINE];
    

    //定义组播结构体
    struct ip_mreqn group;
    confd = socket(AF_INET,SOCK_DGRAM,0);

    //初始化本地端地址
    bzero(&localaddr,sizeof(localaddr));
    localaddr.sin_family = AF_INET;
    inet_pton(AF_INET,"0.0.0.0",&localaddr.sin_addr.s_addr);
    localaddr.sin_port = htons(CLIENT_PORT);

    bind(confd,(struct sockaddr *)&localaddr,sizeof(localaddr));

    //设置组地址
    inet_pton(AF_INET,GROUP,&group.imr_multiaddr);
    //本地任意
    inet_pton(AF_INET,"0.0.0.0",&group.imr_address);
    //eth0
    group.imr_ifindex = if_nametoindex("eth0");
    setsockopt(confd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&group,sizeof(group));

    while(1)
    {
        len = recvfrom(confd,buf,sizeof(buf),0,NULL,0);
        write(STDERR_FILENO,buf,len);
    }

    close(confd);

    return 0;
}

setsockopt の役割

1. ポートの多重化

2.バッファサイズを設定する

3.ブロードキャスト権限を開く

4.マルチキャスト許可を開く

 

おすすめ

転載: blog.csdn.net/weixin_46120107/article/details/126716494