通过 EPOLL 解决客户端同时连接多服务器的问题

项目需求是 程序上 同时配置了多个服务端 设备

每隔一段时间需要 比如1分钟 连一下服务器看下是否连通

并将结果上报给平台

原来是用线程池来做的

具体大概就是 定时器到了之后

遍历设备列表 找到设备之后 通过 socket连接 发送一个指令 等待服务器返回 用来检查是否在线

这样的问题是 如果设备不是很多的话 还好 但是如果 有上百个设备 的话

每一轮遍历需要很长时间

后来 看了EPOLL尝试一下

相当于是改成单线程了 但是效果不是很好

基本上还是相当于单线程 测试结果感觉还是单线程在跑

后期改成协程试下看看

cpp 复制代码
bool QMCY_APP::CreateEPOLL()
{

	m_epoll_fd = epoll_create1(0);
	if (m_epoll_fd < 0)
	{
		printf("epoll_create failed\n");
		return false;
	}

	return true;
}
cpp 复制代码
bool QMCY_APP::Add2Epoll(std::shared_ptr<IQMCY>  led)
{
	int fd;
	auto ip = led->NVR_GetIP().c_str();
	auto port = led->NVR_GetPort();


	struct sockaddr_in my_addr;
	socklen_t peer_addr_size;

	

	fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);

	if (fd == -1)
	{
		printf("Add2Epoll Create socket failed\n");
		return false;
	}

	memset(&my_addr, 0, sizeof(my_addr));
	my_addr.sin_family = AF_INET;
	my_addr.sin_addr.s_addr = inet_addr(ip);
	my_addr.sin_port = htons(port);

	int ret = connect(fd, (struct sockaddr*)&my_addr, sizeof(my_addr));

	if (ret == 0) {
		puts("connect successfully!");
		return false;
	}

	if (errno != EINPROGRESS) printf("Add2Epoll success [%s:%d] \n",ip,port);


	struct epoll_event ev;
	
	ev.events = EPOLLOUT |EPOLLET |EPOLLIN;
	ev.data.fd = fd;

	if (epoll_ctl(m_epoll_fd, EPOLL_CTL_ADD, fd, &ev) == -1)
	{
		printf("epoll_ctl failed\n");
		return false;
	}

	m_led_all.insert(std::pair<int,std::shared_ptr<IQMCY>>(fd,led));
	led->NVR_ResetState();
	return true;
}
cpp 复制代码
bool QMCY_APP::HandleEPOLL()
{
	int timeout = 3000;	
	auto index = 0;

	struct epoll_event events[MAX_EVENTS];

	while(index <m_led_all.size()*2)
	{
		int nfds = epoll_wait(m_epoll_fd, events, MAX_EVENTS, timeout);

		if (nfds < 0) {
			printf("epoll_wait\n");
		} else if (nfds == 0) {
			printf("epoll_wait timeout\n");
		} else 
		{
			for (int n = 0; n < nfds; ++n) 
			{
				printf("epoll_wait nfds:%d events:%d\n",nfds,events[n].events);		 	
				if (events[n].data.fd && (events[n].events & EPOLLOUT)) 
				{
					int connect_error = 0;
					socklen_t len = sizeof(connect_error);
					if(getsockopt(events[n].data.fd, SOL_SOCKET, SO_ERROR, (void*)(&connect_error), &len) < 0)
					{
						printf("getsockopt error\n");
						continue;
					}

					if (connect_error != 0) 
					{
						printf("fd:[%d] connect: %s\n",events[n].data.fd, strerror(connect_error));
						continue;
					}
					else
					{
						auto fd = events[n].data.fd;
						auto led = m_led_all[fd];
						printf("QMCY 00000000000000000 connect to led success [ip:%s  port:%d]\n",led->NVR_GetIP().c_str(),led->NVR_GetPort());

						struct epoll_event ev = {0};
						ev.events = EPOLLET |EPOLLIN;
						ev.data.fd = fd;
						epoll_ctl(m_epoll_fd, EPOLL_CTL_MOD, fd, &ev);

						led->NVR_ProbeOnline(fd);
					}
				}
				else if (events[n].data.fd && (events[n].events & EPOLLIN))
				{
					char buf[BUFSIZ] = {0};
					int nread,n = 0;  
					auto fd = events[n].data.fd;
					while ((nread = read(fd, buf + n, BUFSIZ-1)) > 0) {  
					    n += nread;  
						 printf("n=%d nread=%d\n",n,nread);
					}  
					if (nread == -1 && errno != EAGAIN) {  
					    perror("read error");  
						 continue;
					} 
					auto led = m_led_all[fd];

					printf("11111111Read data success [ip:%s	port:%d read=%d]\n",led->NVR_GetIP().c_str(),led->NVR_GetPort(),n);

					if(n>0)
					{
						led->NVR_ProbeAnalyse(buf,n);						
					}


				}
			}
		}
		index++;
		printf("HandleEPOLL  loop index =%d ~~~~~~~~~~~~~~~~~\n",index);
		//sleep(1);
	}

	printf("HandleEPOLL end exit ~~~~~~~~~~~~~~~~~\n");
	return true;
}
cpp 复制代码
bool QMCY_APP::DestroyEPOLL()
{
	if (m_epoll_fd > 0 ) 
	{
		close(m_epoll_fd);
	}

	return true;
}
相关推荐
爱宇阳6 分钟前
Linux 教程:如何查看服务器当前目录中的文件
linux·运维·github
wheeldown11 分钟前
【Linux】Linux 进程通信:System V 共享内存(最快方案)C++ 封装实战 + 通信案例,4 类经典 Bug 快速修复
linux·运维·服务器·开发语言
AORO20251 小时前
防爆手机与普通手机有什么区别?防爆手机哪个牌子好?
运维·服务器·网络·5g·智能手机·信息与通信
爱倒腾的老唐1 小时前
29、构建可视化日志管理服务器
运维·服务器
小王C语言1 小时前
封装红黑树实现mymap和myset
linux·服务器·算法
对岸住着星星1 小时前
断电重启后自动重连WiFi并分配固定IP的Armbian脚本
服务器·网络·tcp/ip
dessler1 小时前
Elasticsearch(ES)-Logstash
linux·运维·elasticsearch
lht6319356122 小时前
Ubuntu Server系统安装谷歌浏览器
linux·运维·ubuntu
hkNaruto2 小时前
【DevOps】基于Nexus部署内网ubuntu 2204系统APT代理镜像仓库操作手册
运维·ubuntu·devops
JanelSirry2 小时前
DevOps是什么,有什么作用,一般用来干嘛
linux·运维·devops