C++ UDP Reliable Transmission Example with Go-Back-N
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.
原文地址: https://www.cveoy.top/t/topic/m9Ve 著作权归作者所有。请勿转载和采集!