以下是一个基于UDP协议的可靠传输例子,使用Go-Back-N协议实现:

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

using namespace std;

const int MAX_PACKET_SIZE = 1024; // 最大数据包大小
const int WINDOW_SIZE = 4; // 窗口大小

struct packet {
    int seqNum; // 序列号
    int size; // 数据大小
    char data[MAX_PACKET_SIZE]; // 数据
};

int main() {
    int sockfd;
    struct sockaddr_in servaddr;
    memset(&servaddr, 0, sizeof(servaddr));

    // 创建UDP套接字
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        cerr << "Failed to create UDP socket" << endl;
        return 1;
    }

    // 设置服务器地址
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(8888);
    servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");

    // 发送数据包
    int seqNum = 0;
    char message[1024];
    while (true) {
        // 构造数据包
        packet p;
        p.seqNum = seqNum;
        p.size = strlen(message);
        strncpy(p.data, message, MAX_PACKET_SIZE);

        // 发送数据包
        sendto(sockfd, &p, sizeof(p), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));

        // 接收ACK
        int ack;
        recvfrom(sockfd, &ack, sizeof(ack), 0, NULL, NULL);

        // 判断ACK是否正确
        if (ack == seqNum) {
            // 发送成功,更新序列号
            seqNum = (seqNum + 1) % WINDOW_SIZE;
        }
    }

    close(sockfd);
    return 0;
}

在服务器端,使用一个数组来保存已接收到的数据包,接收到数据包后,如果序列号正确,则将数据包存入数组,并发送ACK;如果序列号不正确,则直接发送上一个ACK。

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

using namespace std;

const int MAX_PACKET_SIZE = 1024; // 最大数据包大小
const int WINDOW_SIZE = 4; // 窗口大小

struct packet {
    int seqNum; // 序列号
    int size; // 数据大小
    char data[MAX_PACKET_SIZE]; // 数据
};

int main() {
    int sockfd;
    struct sockaddr_in servaddr, cliaddr;
    memset(&servaddr, 0, sizeof(servaddr));
    memset(&cliaddr, 0, sizeof(cliaddr));

    // 创建UDP套接字
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        cerr << "Failed to create UDP socket" << endl;
        return 1;
    }

    // 设置服务器地址
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(8888);
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    // 绑定套接字
    if (bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
        cerr << "Failed to bind UDP socket" << endl;
        return 1;
    }

    // 接收数据包
    packet window[WINDOW_SIZE];
    int expectedSeqNum = 0;
    while (true) {
        packet p;
        socklen_t len = sizeof(cliaddr);
        recvfrom(sockfd, &p, sizeof(p), 0, (struct sockaddr *)&cliaddr, &len);

        // 判断序列号是否正确
        if (p.seqNum == expectedSeqNum) {
            // 存储数据包
            window[expectedSeqNum] = p;

            // 发送ACK
            int ack = p.seqNum;
            sendto(sockfd, &ack, sizeof(ack), 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr));

            // 更新序列号
            expectedSeqNum = (expectedSeqNum + 1) % WINDOW_SIZE;
        } else {
            // 发送上一个ACK
            int ack = (expectedSeqNum - 1 + WINDOW_SIZE) % WINDOW_SIZE;
            sendto(sockfd, &ack, sizeof(ack), 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr));
        }
    }

    close(sockfd);
    return 0;
}
C++ UDP 可靠传输例子

原文地址: https://www.cveoy.top/t/topic/bFTS 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录