windows上C++将网络数据包组合,写入一个文件中的代码
时间: 2024-03-07 21:46:58 浏览: 15
以下是一个简单的示例代码,演示了如何将分包的数据重新组合成一个完整的文件:
```c++
#include <iostream>
#include <fstream>
#include <WinSock2.h> // Winsock2 库
#pragma comment(lib, "ws2_32.lib")
#define BUF_SIZE 1024 // 缓冲区大小
using namespace std;
int main()
{
// 初始化 Winsock 库
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
cout << "WSAStartup failed!" << endl;
return 1;
}
// 创建套接字
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
{
cout << "socket failed!" << endl;
WSACleanup();
return 1;
}
// 连接服务器
SOCKADDR_IN sockAddr;
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 服务器 IP 地址
sockAddr.sin_port = htons(1234); // 服务器端口号
if (connect(sock, (SOCKADDR*)&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR)
{
cout << "connect failed!" << endl;
closesocket(sock);
WSACleanup();
return 1;
}
// 接收数据包并写入文件
ofstream fout("output.txt", ios::binary); // 打开输出文件流
char buf[BUF_SIZE];
int totalSize = 0; // 文件总大小
int recvSize = 0; // 已接收数据大小
int packNum = 0; // 当前接收的包编号
int packCount = 0; // 总包数
while (true)
{
// 接收包头
int headLen = sizeof(int) * 2;
int ret = recv(sock, buf, headLen, 0);
if (ret == SOCKET_ERROR)
{
cout << "recv failed!" << endl;
break;
}
else if (ret == 0)
{
cout << "connection closed!" << endl;
break;
}
// 解析包头
packCount = *(int*)buf;
packNum = *(int*)(buf + sizeof(int));
int packSize = (packNum == packCount) ? (totalSize % BUF_SIZE) : BUF_SIZE;
// 接收包体
ret = recv(sock, buf, packSize, 0);
if (ret == SOCKET_ERROR)
{
cout << "recv failed!" << endl;
break;
}
else if (ret == 0)
{
cout << "connection closed!" << endl;
break;
}
// 将包体写入文件
fout.write(buf, ret);
totalSize += ret;
recvSize += ret;
// 输出进度信息
cout << "Received package " << packNum << "/" << packCount << ", size = " << ret << endl;
// 接收完所有数据后退出循环
if (recvSize == totalSize)
{
break;
}
}
// 关闭套接字
closesocket(sock);
// 关闭输出文件流
fout.close();
// 清理 Winsock 库
WSACleanup();
cout << "Total size = " << totalSize << ", pack count = " << packCount << endl;
return 0;
}
```
在上述代码中,我们通过 recv 函数接收数据包,并将包体写入到输出文件流中,最终组合成一个完整的文件。为了避免粘包和半包问题,我们首先接收包头,解析出包的编号和大小,然后接收包体,最后根据已接收的数据大小与总大小进行比较,判断是否接收完所有数据。