之前尝试过没有成功 改成协程了
但是协程依赖于协程库 所以 重新改成EPOLL 今天试了下 成功了
关键代码
#ifdef EPOLL
bool QMCY_APP::CreateEPOLL()
{
m_epoll_fd = epoll_create1(0);
if (m_epoll_fd < 0)
{
printf("epoll_create failed\n");
return false;
}
return true;
}
bool QMCY_APP::DestroyEPOLL()
{
if (m_epoll_fd > 0 )
{
close(m_epoll_fd);
}
return true;
}
bool QMCY_APP::Add2Epoll(std::shared_ptr<IQMCY> led,bool is_tcp)
{
int fd;
auto ip = led->NVR_GetIP().c_str();
auto port = led->NVR_GetPort();
struct sockaddr_in my_addr;
//socklen_t peer_addr_size;
if(is_tcp)
{
fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
}
else
{
fd = socket(AF_INET, SOCK_DGRAM | 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;
}
bool QMCY_APP::DelFromEPOLL()
{
for(auto item:m_led_all)
{
epoll_ctl(m_epoll_fd, EPOLL_CTL_DEL, item.first, nullptr);
close(item.first);
}
m_led_all.clear();
return true;
}
bool QMCY_APP::HandleEPOLL()
{
int timeout = m_basic_info.read_timeout*1000;
struct epoll_event events[MAX_EVENTS];
while(true)
{
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");
break;
} else
{
for (int index = 0; index < nfds; ++index)
{
if(m_basic_info.debug_mode)
{
printf("epoll_wait nfds:%d events:%d fd = %d\n",nfds,events[index].events,events[index].data.fd);
}
if (events[index].data.fd && (events[index].events & EPOLLOUT))
{
int connect_error = 0;
socklen_t len = sizeof(connect_error);
if(getsockopt(events[index].data.fd, SOL_SOCKET, SO_ERROR, (void*)(&connect_error), &len) < 0)
{
printf("getsockopt error\n");
continue;
}
if (connect_error != 0)
{
if(m_basic_info.debug_mode)
{
printf("fd:[%d] connect: %s\n",events[index].data.fd, strerror(connect_error));
}
continue;
}
else
{
//Connect success
auto fd = events[index].data.fd;
auto led = m_led_all[fd];
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[index].data.fd && (events[index].events & EPOLLIN))
{
char buf[RECVBUFSIZ] = {0};
int nread,offset = 0;
auto fd = events[index].data.fd;
//printf("epoll_wait nfds:%d events:%d fd = %d\n",nfds,events[index].events,events[index].data.fd);
while ((nread = read(fd, buf + offset, BUFSIZ-1)) > 0) {
offset += nread;
}
if (nread == -1 && errno != EAGAIN) {
perror("read error");
continue;
}
auto led = m_led_all[fd];
if(m_basic_info.debug_mode)
{
printf("11111111Read data success [ip:%s port:%d read=%d]\n",led->NVR_GetIP().c_str(),led->NVR_GetPort(),offset);
}
if(offset>0)
{
led->NVR_ProbeAnalyse(buf,offset);
}
}
}
}
}
printf("HandleEPOLL end exit ~~~~~~~~~~~~~~~~~\n");
return true;
}
#endif
调用地方的代码
void QMCY_APP::Report()
{
std::string led_protocol;
std::string led_ip;
int led_port;
bool is_tcp;
double msecs_time1 = 0;
std::unique_lock<std::mutex> lock(m_table_mutex);
jsonxx::json response ;
struct timeval time_before{};
struct timeval time_after{};
m_led_status="Led status:\n";
if(m_basic_info.debug_mode)
{
gettimeofday(&time_before, nullptr);
msecs_time1 = (double)(time_before.tv_sec * 1000) + (double)(time_before.tv_usec / 1000.0);
std::cout<<"Begin Get state from led server"<<std::endl;
}
for(auto it=m_led_table.begin(); it!=m_led_table.end();it++)
{
auto led = it->second;
if(m_run_flag.load() == false || led == nullptr)
{
return;
}
LED_MSG led_msg;
led_msg.msg_id = MSG_GET_LED_STATE;
led_msg.playlist.bmsid = it->first;
if(m_update_flag.load()|| m_run_flag.load() == false)
{
std::cout<<"Updating led table ....................Get led state will not be executed"<<std::endl;
}
else
{
#ifdef EPOLL
std::tie(led_protocol,led_ip,led_port,is_tcp) = led->NVR_GetLedInfo();
Add2Epoll(led,is_tcp);
#else
#ifdef QMCY_THREAD_POOL
m_queue->push_data(led_msg);
#else
auto led = m_led_table[led_msg.playlist.bmsid];
if(led)
{
led->NVR_GetLEDState();
}
#endif
#endif
}
}
#ifdef EPOLL
HandleEPOLL();
DelFromEPOLL();
#endif
int online_count = 0;
for(auto &it :m_led_table)
{
jsonxx::json item;
auto result = it.second ->NVR_GetStatusResult();
std::tie(led_protocol,led_ip,led_port,is_tcp) = it.second->NVR_GetLedInfo();
item["bmsid"]= it.first;
item["status"]= result.first;
m_led_status+="\nBMSID: "+it.first;
m_led_status+=" IP: "+led_ip;
m_led_status+=" Port: "+led_port;
m_led_status+=" Protocol: "+led_protocol;
if(result.first == 0)
{
online_count++;
m_led_status+=" 在线OOOOOOOOOO";
}
else
{
m_led_status+=" 离线XXXXXXXXXXX";
}
item["msg"]= result.second;
m_led_status+=" 附加信息: "+result.second;
response.push_back(std::move(item));
}
m_led_status+="\n总数: "+std::to_string(m_led_table.size())+" 在线:"+std::to_string(online_count)+"\n";
if(m_basic_info.debug_mode)
{
std::cout<<"Report online status [total:"<<m_led_table.size()<<" online:"<<online_count<<"]"<<std::endl;
gettimeofday(&time_after, nullptr);
double msecs_time2 =(double) (time_after.tv_sec * 1000) + (double)(time_after.tv_usec / 1000.0);
auto elapse = msecs_time2-msecs_time1;
printf("Getstate with ST thread takes time:%f \n",elapse);
}
m_get_times++;
m_basic_info.online = "[Total:";
m_basic_info.online+= std::to_string(m_led_table.size());
m_basic_info.online+=" online:";
m_basic_info.online+= std::to_string(online_count);
m_basic_info.online+="]\n";
m_led_status+="\n"+m_basic_info.online;
auto output = response.dump();
if(output.size()>5)
{
//m_led_status = output;
if(auto res = m_http_client->Post(m_basic_info.report_status,output,"application/json"))
{
if (res->status == 200)
{
}
else
{
auto err = res.error();
std::cout << "HTTP error: " << httplib::to_string(err) << std::endl;
}
}
else
{
std::cout<<"Report status to server failed!"<<std::endl;
//zlog_error(g_zlog,"Report status to server[%s:%d] failed!",pHandle->server_ip,pHandle->server_port);
}
}
else
{
std::cout<<"output is invalid size :"<<output.size()<<std::endl;
}
}