概述
一個基于Qt框架實現的UDP主從服務器系統,該系統具備自動主機選舉、故障轉移和狀態同步等關鍵功能,適用于分布式能源管理系統中的設備通信與協調。
系統核心功能
1. 自動主機選舉與故障轉移
系統通過優先級機制實現自動主機選舉,當主機掉線時,系統會自動選擇優先級最高的從機作為新的主機,確保系統持續運行。
關鍵代碼實現:
void MasterServer::voteHostServer()
{// 如果本機不在線,不參與選舉if(mapDeviceInfo.value(mPriority).onLine == false) {return;}// 如果當前只有一個主機,不需要重新選舉if(judgmentMasterCircumstance().size() == 1) {return;}// 按優先級排序所有設備QList<int> listPriority = mapDeviceInfo.keys();std::sort(listPriority.begin(), listPriority.end());// 重置所有設備的主機狀態for(int i = 0; i < listPriority.size(); i++) {mapDeviceInfo[listPriority.at(i)].hostServer = false;}// 選舉優先級最高的在線設備為主機for(int i = 0; i < listPriority.size(); i++) {if(mapDeviceInfo.value(listPriority.at(i)).onLine == true) {mapDeviceInfo[listPriority.at(i)].hostServer = true;qDebug() << QString("%1 成為主機").arg(mapDeviceInfo[listPriority.at(i)].addrIp);// 如果選舉的是本機,更新本機狀態if(listPriority.at(i) == mPriority) {bHost = true;}break;}}
}
2. 設備掉線檢測與通知
系統會定期檢測設備狀態,當發現設備掉線時,會通過UDP廣播通知所有設備更新狀態。
關鍵代碼實現:
void MasterServer::slotTimeOut()
{qint64 curTime = QDateTime::currentSecsSinceEpoch();int priorityDel = -1;// 檢查所有設備狀態for (const auto& priority : mapDeviceInfo.keys()) {// 計算上次收到消息的時間差int deltaT = curTime - mapDeviceInfo.value(priority).lastReciTime;QString localIP = mJsonDevInfo.value("ip").toString();// 忽略本機if(localIP != mapDeviceInfo.value(priority).addrIp) {if(deltaT > TIME_OUT_SECOND) {mapDeviceInfo[priority].dropTimes++;}// 超過最大丟包次數,標記為離線if(mapDeviceInfo[priority].dropTimes > MAX_DROP_TIME) {mapDeviceInfo[priority].onLine = false;mapDeviceInfo[priority].hostServer = false;qDebug() << __FUNCTION__ << mapDeviceInfo[priority].addrIp << "Timeout drop";// 如果掉線的是主機,觸發重新選舉if(mapDeviceInfo[priority].hostServer) {voteHostServer();}}// 超過刪除時間,從列表中移除if(mapDeviceInfo[priority].dropTimes > TIME_OUT_DELETE) {priorityDel = priority;}}}// 移除長時間離線的設備if(priorityDel > 0) {qDebug() << __FUNCTION__ << "time out delete priority" << priorityDel;mapDeviceInfo.remove(priorityDel);}// 更新本機主機狀態bHost = mapDeviceInfo.value(mPriority).hostServer;// 廣播設備狀態信息if(bHost) {// 主機廣播所有設備信息for (const auto& priority : mapDeviceInfo.keys()) {QJsonObject jsonObj;// 填充設備信息...QByteArray ba = simplify(jsonObj);mSocket->writeDatagram(ba, QHostAddress(BROADCAST_ADDRESS), PORT);}} else {// 從機僅廣播本機信息QByteArray ba = simplify(mJsonDevInfo);mSocket->writeDatagram(ba, QHostAddress(BROADCAST_ADDRESS), PORT);}// 發出信號通知UI更新emit signalDevInfo(bHost, mapDeviceInfo);
}
3. 設備狀態同步機制
系統通過UDP廣播實現設備間狀態同步,確保所有設備都能獲取最新的系統狀態。
關鍵代碼實現:
void MasterServer::analysisJsonShowInfo(const QByteArray& array, const QHostAddress& addr)
{QJsonObject json = QJsonDocument::fromJson(array).object();int priority = json.value("priority").toInt();bool host = json.value("hostServer").toBool();bool online = json.value("onLine").toBool();// 更新設備信息mapDeviceInfo[priority].addrIp = json.value("ip").toString();mapDeviceInfo[priority].priority = priority;mapDeviceInfo[priority].hostServer = host;mapDeviceInfo[priority].onLine = online;// 更新其他設備數據...// 如果是本機消息,更新接收時間
#ifdef ARM_LINUXif(addr.toString() == json.value("ip").toString())
#endif{mapDeviceInfo[priority].lastReciTime = QDateTime::currentSecsSinceEpoch();mapDeviceInfo[priority].dropTimes = 0;}// 如果只有本機在線,自動成為主機if(mapDeviceInfo.size() == 1 && priority == mPriority) {mapDeviceInfo[priority].hostServer = true;bHost = true;} else {// 否則進行主機選舉voteHostServer();}// 通知UI更新從機信息emit signalSlaveDevInfoUi(mapDeviceInfo);
}
基于優先級的分布式主從架構,工作流程分為四個階段:1)初始化階段各設備確定自身優先級并監聽網絡;2)選舉階段通過優先級比較自動選出主機;3)運行階段主機協調系統、廣播全局狀態,從機上報自身狀態;4)容錯階段實時監測設備狀態,主機故障時立即觸發重新選舉,從機掉線時自動更新拓撲。系統核心優勢體現在三個方面:高可用性方面,采用無單點故障設計,秒級故障轉移確保服務連續性;狀態一致性方面,通過UDP廣播和主機維護全局視圖保證數據同步;靈活性方面,支持優先級動態配置和網絡參數調優,適應不同規模場景。此外,高效的UDP通信機制和精簡的數據封裝保證了系統在資源受限環境下的穩定運行。