UDP广播发送文件

需求。一台服务器给N台客户端通过一个路由局域网发送文件,S(1)/C(N)模型。服务器是一台PC。或者pad

测试。http下载。客户端同时请求下载时候下载速度基本停止,服务器也会有异常。

       udp分发。广播丢包太严重。基本丢包率在60%。路由是500左右的TP-LINK。单播丢包率在1%..


以下是一个简单的 Windows C++ UDP 广播发送文件的示例代码,包括服务端分包发送和客户端接收并写入文件的过程: 服务端代码: ```c++ #include <iostream> #include <fstream> #include <cstring> #include <WinSock2.h> #pragma comment(lib, "ws2_32.lib") using namespace std; const int BUF_SIZE = 1024; // 每个包的大小 const int MAX_PACK_NUM = 10000; // 最大包数 // 包头结构体,包含包序号、包长度和包头标记 struct PackHeader { int seq; int len; int mark; }; int main() { // 初始化 WinSock2 库 WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); // 创建 UDP 套接字 SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock == INVALID_SOCKET) { cerr << "socket failed with error: " << WSAGetLastError() << endl; WSACleanup(); return 1; } // 设置广播选项 bool bOptVal = true; int bOptLen = sizeof(bool); setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&bOptVal, bOptLen); // 绑定本地地址和端口 sockaddr_in localAddr; localAddr.sin_family = AF_INET; localAddr.sin_port = htons(8888); localAddr.sin_addr.s_addr = htonl(INADDR_ANY); bind(sock, (sockaddr*)&localAddr, sizeof(localAddr)); // 打开文件 ifstream file("test.txt", ios::binary); if (!file.is_open()) { cerr << "open file failed" << endl; closesocket(sock); WSACleanup(); return 1; } // 发送文件 char buf[BUF_SIZE]; PackHeader header; int seq = 0; int len; while (!file.eof() && seq < MAX_PACK_NUM) { // 读取数据 file.read(buf, BUF_SIZE); len = file.gcount(); if (len == 0) { break; } // 构造包头 header.seq = seq++; header.len = len; header.mark = 0x12345678; // 发送数据 sendto(sock, (char*)&header, sizeof(header), 0, (sockaddr*)&localAddr, sizeof(localAddr)); // 发送包头 sendto(sock, buf, len, 0, (sockaddr*)&localAddr, sizeof(localAddr)); // 发送数据 } // 关闭文件和套接字 file.close(); closesocket(sock); WSACleanup(); return 0; } ``` 客户端代码: ```c++ #include <iostream> #include <fstream> #include <cstring> #include <WinSock2.h> #pragma comment(lib, "ws2_32.lib") using namespace std; const int BUF_SIZE = 1024; // 每个包的大小 const int MAX_PACK_NUM = 10000; // 最大包数 // 包头结构体,包含包序号、包长度和包头标记 struct PackHeader { int seq; int len; int mark; }; int main() { // 初始化 WinSock2 库 WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); // 创建 UDP 套接字 SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock == INVALID_SOCKET) { cerr << "socket failed with error: " << WSAGetLastError() << endl; WSACleanup(); return 1; } // 设置广播选项 bool bOptVal = true; int bOptLen = sizeof(bool); setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&bOptVal, bOptLen); // 绑定本地地址和端口 sockaddr_in localAddr; localAddr.sin_family = AF_INET; localAddr.sin_port = htons(8889); localAddr.sin_addr.s_addr = htonl(INADDR_ANY); bind(sock, (sockaddr*)&localAddr, sizeof(localAddr)); // 创建文件 ofstream file("recv.txt", ios::binary); if (!file.is_open()) { cerr << "create file failed" << endl; closesocket(sock); WSACleanup(); return 1; } // 接收包并写入文件 char buf[BUF_SIZE]; PackHeader header; int totalLen = 0; int seq = 0; int len; while (seq < MAX_PACK_NUM) { // 接收包头 int addrLen = sizeof(sockaddr_in); int ret = recvfrom(sock, (char*)&header, sizeof(header), 0, (sockaddr*)&localAddr, &addrLen); if (ret == SOCKET_ERROR) { cerr << "recvfrom failed with error: " << WSAGetLastError() << endl; break; } if (header.mark != 0x12345678) { cerr << "invalid header mark" << endl; break; } // 接收数据 ret = recvfrom(sock, buf, BUF_SIZE, 0, (sockaddr*)&localAddr, &addrLen); if (ret == SOCKET_ERROR) { cerr << "recvfrom failed with error: " << WSAGetLastError() << endl; break; } len = ret; // 检查包序号 if (header.seq != seq) { cerr << "invalid seq number" << endl; break; } // 写入文件 file.write(buf, len); totalLen += len; seq++; // 全部接收完毕 if (totalLen >= header.len) { break; } } // 关闭文件和套接字 file.close(); closesocket(sock); WSACleanup(); return 0; } ``` 这个示例代码只是一个简单的实现,实际应用中还需要考虑数据包丢失、重、超时等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

钱王拳王

感谢 first big ge

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值