我用C++实现一个小的demo,windows下socket通信(TCP/IP),现在我想测试他俩之间的传输速率,像iperf3那样。现在遇到了一点问题,我不知道这个数据该怎么定义,是需要特定格式吗?收发功能需要特殊方法吗?下面是我的代码,直接生成了300M的数据,看看一秒呢服务端能接收到多少,想请假一下这个做法是否正确
Client
#include<iostream>
#include<winsock2.h>
#include<ws2tcpip.h>
#include<string>
#include<chrono>
#include <vector>
#include <random>
#pragma comment(lib,"ws2_32.lib")
std::vector<char> generateLargeData(size_t dataSize)
{
std::vector<char> data(dataSize);
std::default_random_engine generator;
std::uniform_int_distribution<int> distribution(0, 255);
for (size_t i = 0; i < dataSize; ++i) {
data[i] = static_cast<char>(distribution(generator));
}
return data;
}
int ClientSpeed() {
WSADATA wsaData;
SOCKET clientSocket;
sockaddr_in serverAddr;
WORD sockVersion = MAKEWORD(2, 2);
//初始化WSAStartup 函数
if (WSAStartup(sockVersion, &wsaData) != 0) {
std::cerr << "WSAStartup() error!" << std::endl;
return 1;
}
clientSocket = socket(AF_INET, SOCK_STREAM, 0);
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(8888);
if (inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr) <= 0) {
std::cerr << "Invalid address/Address not supported." << std::endl;
closesocket(clientSocket);
WSACleanup();
return 1;
}
if (connect(clientSocket, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
std::cerr << "Connect failed: " << WSAGetLastError() << std::endl;
closesocket(clientSocket);
WSACleanup();
return 1;
}
std::cout << "Client Connected to server!" << std::endl;
// 生成大量数据
auto largeData = generateLargeData(300 * 1024 * 1024);
size_t totalBytesSent = 0;
auto start = std::chrono::high_resolution_clock::now();
auto end = start;
// 循环发送数据,直到一秒钟结束
while (std::chrono::duration_cast<std::chrono::seconds>(end - start).count() < 1) {
int bytesSent = send(clientSocket, largeData.data() + totalBytesSent, largeData.size() - totalBytesSent, 0);
if (bytesSent > 0) {
totalBytesSent += bytesSent;
}
else {
// 处理错误情况
std::cerr << "Send failed: " << WSAGetLastError() << std::endl;
break;
}
end = std::chrono::high_resolution_clock::now();
}
double speedMBps = totalBytesSent / 1024.0 / 1024.0; // 计算总发送速度,单位为MB/s
// 输出结果
std::cout << "Total data sent in one second: " << totalBytesSent << " bytes." << std::endl;
std::cout << "Speed: " << speedMBps << " MB/s" << std::endl;
// 清理
closesocket(clientSocket);
WSACleanup();
return 0;
}
Server
#include<iostream>
#include<WinSock2.h>
#include <ws2tcpip.h> // 包括 inet_ntop
using namespace std;
#pragma comment(lib,"ws2_32.lib")
int Server()
{
//初始化WSA
WORD sockVersion = MAKEWORD(2, 2);
WSADATA wsaData;//用于存放 socket 的初始化信息
//int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);
if (WSAStartup(sockVersion, &wsaData) != 0)
{
cout << "WSAStartup() error!" << endl;
return 0;
}
//创建套接字
SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (slisten == INVALID_SOCKET)
{
cout << "socket error !" << endl;
return 0;
}
//绑定IP和端口
sockaddr_in sin;//ipv4的指定方法是使用struct sockaddr_in类型的变量 ipv6 使用struct sockaddr_in6
sin.sin_family = AF_INET;
sin.sin_port = htons(8888);//设置端口。htons将主机的unsigned short int转换为网络字节顺序 网络要用大端序如果本身是大端序则不会有改变
sin.sin_addr.S_un.S_addr = INADDR_ANY;//IP地址设置成INADDR_ANY, 服务器能后接受来自任何本地的连接请求
//bind函数把一个地址族中的特定地址赋给scket。
if (bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)
{
printf("bind error !");
}
//开始监听listen函数的这个参数控制的是在服务器尚未accept之前,能够排队等待的连接请求的数量
if (listen(slisten, 10) == SOCKET_ERROR)
{
cout << "listen error !" << endl;
return -1;
}
sockaddr_in remoteAddr;//sockaddr_in常用于socket定义和赋值,sockaddr用于函数参数
int nAddrlen = sizeof(remoteAddr);
while (true)
{
//循环接收数据 listen Socket负责接纳新的连接请求,而client Socket则负责处理具体的数据交换
SOCKET sclient;
cout << "TCP等待连接。。。" << endl;
sclient = accept(slisten, (sockaddr*)&remoteAddr, &nAddrlen);
if (sclient == INVALID_SOCKET)
{
cout << "accept error !" << endl;
continue;
}
char str[INET_ADDRSTRLEN]; // INET_ADDRSTRLEN是为IPv4地址定义的长度
inet_ntop(AF_INET, &(remoteAddr.sin_addr), str, INET_ADDRSTRLEN);
cout << "接收到一个连接:" << str << endl;
while (true) { // 为当前连接持续处理数据
char revData[256];
int ret = recv(sclient, revData, 255, 0);
if (ret > 0) {
revData[ret] = 0x00; // 确保字符串以null终结
const char* sendData = "你好,TCP客户端";
send(sclient, sendData, strlen(sendData), 0);
}
else if (ret < 0) {
cout << "没有接收到数据" << endl;
closesocket(sclient);
break;
}
else {
cout << "数据接收完成" << endl;
closesocket(sclient);
break;
}
}
}
closesocket(slisten);
WSACleanup();
system("pause");
//return 0;
}