cネットワークプログラミングでのUDP統計パケット損失

前書き

このプロジェクトは、LANの下の2つのホスト間で完了します。一方のホストが他方のホストに100パケットを継続的に送信し、他方のホストが実際に受信したパケット数をカウントする必要があります。

プログラミング

1.設定環境
実験はDev C ++で開発されており、Windowsネットワークプログラミングの関連APIを使用するため、<winsock2.h>ヘッダーファイルをインクルードし、静的リンクファイルwsock32.libをプロジェクトに追加する必要があります。
静的リンクファイルを追加する方法:プロジェクト->プロジェクトプロパティ->パラメータ->リンク->ライブラリまたはオブジェクトを追加し、wsock32.libを見つけてプロジェクトに追加します。
送信者と受信者として同じLANにある2つのホストをそれぞれ選択します。ipはそれぞれ192.168.1.109と192.168.1.108です。

2.プログラムの設計
送信側ホストで新しいプロジェクトを作成し、必要なヘッダーファイルと静的リンクファイルをインポートしてから、送信側プログラムを
作成します受信側ホストで新しいプロジェクトを作成し、必要なヘッダーファイルと静的リンクファイルをインポートします。次に、受信側のプログラムを記述します。
送信側プログラムは、大まかに次の部分に分かれてい
ます。socket()を使用してソケットserverscokを作成し、bind()を使用してホストのIPとソケットのポートをバインドし、struct sockaddr_inオブジェクトを作成して受信側のIPとポート番号を使用しますこれに割り当て、sendto()を使用して、100個のUDPデータパケットをループにあるサーバーソックから受信側に送信し、closesocket()を使用して、ソケットに割り当てられているリソースを解放します。
受信側のプログラムは、大きく分けて次の部分に分かれてい
ます。socket()を使用してソケットclientockを作成し、bind()を使用してホストのIPとソケットのポートをバインドし、recvfrom()を使用してループで送信者を受信します。着信パケットの場合、失われたパケットの数を数え、closesocket()を使用してソケットに割り当てられているリソースを解放します。

プログラムの実現

送信者

//server which send messages to client

#include<winsock2.h>
#include<stdio.h>
#include<stdlib.h>
#define WSVERS MAKEWORD(2, 0)
void errexit(const char*, ...);//错误信息打印函数

int main(int argc, char* argv[]) {
    
    
    struct sockaddr_in sock_address, to_address;
    SOCKET serversock;
    WSADATA wsadata;
    
    if (WSAStartup(WSVERS, &wsadata) != 0) {
    
    
        errexit("WSAStartup failed\n");
    }
    //create and bind serversock
    serversock = socket(AF_INET, SOCK_DGRAM, 0); //获得serversock
    sock_address.sin_family = AF_INET; //设置地址家族
    sock_address.sin_port = htons(12345); //设置端口
    sock_address.sin_addr.s_addr = inet_addr("192.168.1.109"); //设置地址
    int flag = bind(serversock, (struct sockaddr*) &sock_address, sizeof(struct sockaddr));
    if (flag != 0) errexit("bind falied.\n");

    char buf[4096];
    
    //initiate to_address with client's address
    to_address.sin_family = AF_INET;
    to_address.sin_port = htons(12345); //设置端口
    const char * addr = "192.168.1.108";
    to_address.sin_addr.s_addr = inet_addr(addr); //设置地址
     
    int count = 0;
    while (++count <= 101) {
    
    
        char buf[4096];
        if (count <= 100)
            sprintf(buf, "Hello, I'm number %d of packet sent from %s", count, "192.168.1.109");
        else 
            sprintf(buf, "end of messages");
        flag = sendto(serversock, buf, 4096, 0, (struct sockaddr*) &to_address, sizeof(struct sockaddr));
        if (flag == -1) {
    
    
            errexit("send falied, errno = %d\n", GetLastError());
        }
        printf("send message '%s' to %s\n", buf, addr);
    }
    
    (void)closesocket(serversock);

    return 0;
    
}


void errexit(const char *format, ...) {
    
    
    va_list args;

    va_start(args, format);
    vfprintf(stderr, format, args);
    va_end(args);
    WSACleanup();
    exit(1);

}

受信終了

//client which receive messages from server

#include<winsock2.h>
#include<stdio.h>
#include<stdlib.h>
#define WSVERS MAKEWORD(2, 0)
void errexit(const char*, ...);//错误信息打印函数

int main(int argc, char* argv[]) {
    
    
    struct sockaddr_in sock_address, from_address;
    SOCKET clientsock;
    WSADATA wsadata;
    
    if (WSAStartup(WSVERS, &wsadata) != 0) {
    
    
        errexit("WSAStartup failed\n");
    }
    //create and bind serversock
    clientsock = socket(AF_INET, SOCK_DGRAM, 0); //获得serversock
    sock_address.sin_family = AF_INET; //设置地址家族
    sock_address.sin_port = htons(12345); //设置端口
    sock_address.sin_addr.s_addr = inet_addr("192.168.1.108"); //设置地址
    int flag = bind(clientsock, (struct sockaddr*) &sock_address, sizeof(struct sockaddr));
    if (flag != 0) errexit("bind falied.\n");

    
     
    char buf[4096];
    
    int count = 0;
    int fromlen;
    const char* endquotes = "end of messages";
    while (true) {
    
    
        flag = recvfrom(clientsock, buf, 4096, 0, NULL, NULL);
        if (flag == -1) {
    
    
            errexit("receive falied, errno = %d\n", GetLastError());
        }
        printf("%s\n", buf);
        if (strcmp(endquotes, buf) == 0) break;
        ++count;
        printf("count: %d\n", count);
    }
    printf("\n\ntotal 100, actually receive %d, lost %d\n", count, 100 - count);
    (void)closesocket(clientsock);

    return 0;
    
}

void errexit(const char *format, ...) {
    
    
    va_list args;

    va_start(args, format);
    vfprintf(stderr, format, args);
    va_end(args);
    WSACleanup();
    exit(1);

}

演算結果

最初に受信側プログラムを実行し、それをブロッキング状態にしてから、送信側プログラムを実行します。
結果は、送信者が101個のUDPデータパケット(送信の終了を示す最後のデータパケットを含む)を正常に送信し、受信者
ここに画像の説明を挿入
が100個のパケットのうち71個のパケットを正常に受信し、29個のパケットを失ったことを示しています。
ここに画像の説明を挿入
ここに画像の説明を挿入

総括する

プログラムにはまだ少し欠陥があります。終了情報としてのパケット自体が失われた場合、受信側は終了情報を受信するまで待機しますが、全体的な状況には影響しません(大した問題が繰り返されます)。したがって、変更しません。

おすすめ

転載: blog.csdn.net/weixin_43867940/article/details/106414102
おすすめ