C++ UDP 可靠传输例子
以下是一个基于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;
}
原文地址: https://www.cveoy.top/t/topic/bFTS 著作权归作者所有。请勿转载和采集!