项目(百万并发网络通信架构)9.1---设计多线程客户端测试程序,分组高频发送数据

一、前言

  • 接下来几篇文章中将设计多线程的知识,本篇文章将使用C++11提供的多线程接口设计客户端程序,创建指定数量的客户端,然后将客户端的任务平均到每个线程中进行执行
  • 注意:并不对之前的客户端实现代码EasyTcpClient.hpp做任何修改,是通过设计main()函数,设计多线程客户端测试程序

二、代码设计

  • 代码设计主要的思想有:
    • 创建一个UI线程,其线程执行函数为cmdThread(),用于输入命令退出程序
    • 创建一个全局客户端数组client,其中存储客户端对象
    • 为了将所有客户端的任务平均,我们设定了一个全局变量tCount,代表要创建多少个客户端数据处理线程
    • 在main()中创建tCount数量的线程,每个线程中所操作的客户端数量平均,线程执行函数为sendThread()
    • 因为创建的线程都是以detach()分离的,因此为了防止主程序比子线程提前退出,我们在main()的最后使用一个getchar()函数阻塞在程序中。如果想要终止程序,那么就回车,整个程序都终止
  • 代码中的cCount和tCount可以修改,分别达到不同的效果。例如:
    • cCount=100,tCount=4,代表创建4个线程,100个客户端,每个线程处理25个客户端
    • cCount=1000,tCount=10,代表创建10个线程,1000个客户端,每个线程处理100个客户端
#include "EasyTcpClient.hpp"
#include <thread>

bool g_bRun = false;
const int cCount = 100;  //客户端的数量
const int tCount = 4;    //线程的数量
EasyTcpClient* client[cCount];//客户端的数组

void cmdThread();
void sendThread(int id);

int main()
{
	g_bRun = true;

	//UI线程
	std::thread t(cmdThread);
	t.detach();

	//启动发送线程
	for (int n = 0; n < tCount; ++n)
	{
		std::thread t(sendThread, n + 1);
		t.detach();
	}

	std::cout << "客户端停止工作!" << std::endl;
	getchar();
	return 0;
}

void cmdThread()
{
	char cmdBuf[256] = {};
	while (true)
	{
		std::cin >> cmdBuf;
		if (0 == strcmp(cmdBuf, "exit"))
		{
			g_bRun = false;
			break;
		}
		else {
			std::cout << "命令不识别,请重新输入" << std::endl;
		}
	}
}

void sendThread(int id)
{
	/*
		下面这几个变量是为了平均每个线程创建的客户端的数量:
			例如,本次测试时客户端数量为1000,线程数量为4,那么每个线程应该创建250个客户端
				线程1:c=250,begin=0,end=250
				线程2:c=250,begin=250,end=500
				线程3:c=250,begin=500,end=750
				线程4:c=250,begin=750,end=1000
	*/
	int c = cCount / tCount;
	int begin = (id - 1)*c;
	int end = id*c;

	for (int n = begin; n < end; ++n) //创建客户端
	{
		client[n] = new EasyTcpClient;
	}
	for (int n = begin; n < end; ++n) //让每个客户端连接服务器
	{
		client[n]->ConnectServer("192.168.0.105", 4567);
		printf("Connect=%d\n", n);
	}

	Login login;
	strcpy(login.userName, "dongshao");
	strcpy(login.PassWord, "123456");
	//循环向服务端发送消息
	while (g_bRun)
	{
		for (int n = begin; n < end; ++n)
		{
			client[n]->SendData(&login);
			//client[n]->Onrun();
		}
	}

	//关闭客户端
	for (int n = begin; n < end; ++n)
	{
		client[n]->CloseSocket();
	}
}

三、测试4线程100客户端连接

  • 客户端测试程序就是上面的代码:
    • cCount代表客户端数量,为100
    • tCount代表线程数量,为4
    • 因此每个线程处理25个客户端的数据发送
  • 服务端测试程序如下:
#include "EasyTcpServer.hpp"
#include "MessageHeader.hpp"

int main()
{
	EasyTcpServer server;
	server.Bind("192.168.0.105", 4567);
	server.Listen(5);

	while (server.isRun())
	{
		server.Onrun();
	}

	server.CloseSocket();
	std::cout << "服务端停止工作!" << std::endl;

	getchar();  //防止程序一闪而过
	return 0;
}
  • 测试结果如下图所示:
    • 左侧为服务端,右侧为客户端
    • 服务端每秒接收到的数据包数量大概在10万左右

  • 资源监视器如下图所示:
    • 可以看到网络总带宽大概1Gbps
    • 可以看到服务端接收到的数据字节数为一亿多,与上图相符合(上图中服务端每秒收到10万左右数据包,每个数据包为1000KB,因此相乘就是一千多万)

四、测试4线程1000客户端连接

  • 客户端测试程序就是上面的代码:
    • cCount代表客户端数量,修改为1000即可
    • tCount代表线程数量,仍然为4
    • 因此每个线程处理250个客户端的数据发送
  • 服务端测试程序同上
  • 测试结果如下图所示:
    • 左侧为服务端,右侧为客户端
    • 服务端每秒接收到的数据包数量大概在3万左右

  • 资源监视器如下图所示:
    • 可以看到网络总带宽大概700Mbps
    • 可以看到服务端接收到的数据字节数为三千多万左右,与上图相符合(上图中服务端每秒收到3万左右数据包,每个数据包为1000KB,因此相乘就是三千多万)

发布了1594 篇原创文章 · 获赞 1190 · 访问量 57万+

猜你喜欢

转载自blog.csdn.net/qq_41453285/article/details/105451473