C++ UDP Reliable Transmission Example with Go-Back-N

This example demonstrates reliable data transmission over UDP using the Go-Back-N protocol in C++. It includes both the client and server code for sending and receiving data packets with sequence numbers and acknowledgments (ACKs).

Client Code

#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; // Maximum packet size
const int WINDOW_SIZE = 4; // Window size

struct packet {
    int seqNum; // Sequence number
    int size; // Data size
    char data[MAX_PACKET_SIZE]; // Data
};

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

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

    // Set server address
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(8888);
    servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");

    // Send data packets
    int seqNum = 0;
    char message[1024];
    while (true) {
        // Construct packet
        packet p;
        p.seqNum = seqNum;
        p.size = strlen(message);
        strncpy(p.data, message, MAX_PACKET_SIZE);

        // Send packet
        sendto(sockfd, &p, sizeof(p), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));

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

        // Check if ACK is correct
        if (ack == seqNum) {
            // Send successful, update sequence number
            seqNum = (seqNum + 1) % WINDOW_SIZE;
        }
    }

    close(sockfd);
    return 0;
}

Server Code

#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; // Maximum packet size
const int WINDOW_SIZE = 4; // Window size

struct packet {
    int seqNum; // Sequence number
    int size; // Data size
    char data[MAX_PACKET_SIZE]; // Data
};

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

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

    // Set server address
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(8888);
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

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

    // Receive data packets
    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);

        // Check if sequence number is correct
        if (p.seqNum == expectedSeqNum) {
            // Store packet
            window[expectedSeqNum] = p;

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

            // Update sequence number
            expectedSeqNum = (expectedSeqNum + 1) % WINDOW_SIZE;
        } else {
            // Send previous ACK
            int ack = (expectedSeqNum - 1 + WINDOW_SIZE) % WINDOW_SIZE;
            sendto(sockfd, &ack, sizeof(ack), 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr));
        }
    }

    close(sockfd);
    return 0;
}

Explanation:

  • Go-Back-N Protocol: This protocol ensures reliable data transmission by using sequence numbers and acknowledgments. The client sends packets with increasing sequence numbers and waits for acknowledgments from the server. If an acknowledgment is not received within a timeout period, the client retransmits the packets starting from the missing sequence number.
  • Client: The client code creates a UDP socket, sets the server address, and sends data packets. It then receives acknowledgments from the server. If the received acknowledgment matches the sent packet's sequence number, the client moves to the next packet. Otherwise, it retransmits the packets.
  • Server: The server code creates a UDP socket, binds it to a specific port, and receives packets. It maintains a window of expected packets and checks the sequence number of each received packet. If the sequence number is correct, it stores the packet and sends an acknowledgment. Otherwise, it sends the last valid acknowledgment.
  • Window Size: The window size defines how many packets the client can send without waiting for acknowledgments. In this example, the window size is set to 4.

This is a basic example of reliable UDP transmission using the Go-Back-N protocol. You can extend this code to handle various scenarios, such as packet loss, timeouts, and error handling.

C++ UDP Reliable Transmission Example with Go-Back-N

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

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