RtpServer.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. #include "RtpServer.h"
  2. #include <QTcpSocket>
  3. #include <QNetworkInterface>
  4. #include <QHostAddress>
  5. #include "ThreadManager.h"
  6. #include "ThreadCompareItemManager.h"
  7. #include "SystemConfig.h"
  8. RTPServer::RTPServer(QObject *parent)
  9. : QObject(parent), m_tcpServer(nullptr), m_port(8808)
  10. {
  11. }
  12. RTPServer::~RTPServer()
  13. {
  14. if (m_tcpServer)
  15. {
  16. m_tcpServer->close();
  17. delete m_tcpServer;
  18. m_tcpServer = nullptr;
  19. }
  20. }
  21. /**
  22. * @brief 启动RTP服务
  23. * @param port 监听端口
  24. * @return 成功返回true,失败返回false
  25. */
  26. bool RTPServer::thread_task(int port)
  27. {
  28. m_logger = spdlog::get("RTPServer");
  29. if (!m_logger)
  30. {
  31. fmt::print("RTPServer: Failed to get logger instance.\n");
  32. return false;
  33. }
  34. SPDLOG_LOGGER_INFO(m_logger, "♫ 开启 RTPServer 服务线程");
  35. if(m_tcpServer == nullptr)
  36. {
  37. m_tcpServer = new QTcpServer(this);
  38. }
  39. m_port = port;
  40. if(!m_tcpServer->listen(QHostAddress::Any, m_port))
  41. {
  42. SPDLOG_LOGGER_ERROR(m_logger, "Failed to start RTP server on port {}", m_port);
  43. SPDLOG_LOGGER_ERROR(m_logger, "错误信息: {}", m_tcpServer->errorString().toStdString());
  44. return false;
  45. }
  46. /* 查找到出口IP */
  47. m_localIP = SysConfig.getBaseConfigSrc().strServerIP;
  48. if(m_localIP.isEmpty())
  49. {
  50. SPDLOG_LOGGER_ERROR(m_logger, "未设置服务器监听IP,无法监听客户端连接");
  51. }
  52. connect(m_tcpServer, &QTcpServer::newConnection, this, &RTPServer::do_newConnection);
  53. connect(m_tcpServer, &QTcpServer::acceptError, this, &RTPServer::do_error);
  54. /* 开启心跳定时器 */
  55. m_timerHeartbeat.setTimerType(Qt::PreciseTimer);
  56. m_timerHeartbeat.setSingleShot(false);
  57. m_timerHeartbeat.setInterval(1000);
  58. connect(&m_timerHeartbeat, &QTimer::timeout, this, &RTPServer::do_heartbeatTimeout);
  59. m_timerHeartbeat.start();
  60. /* 开启事件循环 */
  61. m_isStoped.store(false);
  62. m_eventLoop.exec();
  63. m_isStoped.store(true);
  64. SPDLOG_LOGGER_INFO(m_logger, "♫ RTPServer 线程结束运行");
  65. return true;
  66. }
  67. /* 停止线程 */
  68. void RTPServer::stopThreadBlock()
  69. {
  70. if(m_eventLoop.isRunning())
  71. {
  72. m_eventLoop.quit();
  73. }
  74. while(!m_isStoped.load())
  75. {
  76. std::this_thread::sleep_for(std::chrono::milliseconds(10));
  77. }
  78. }
  79. /* 处理新连接 */
  80. void RTPServer::do_newConnection()
  81. {
  82. QTcpSocket* clientSocket = m_tcpServer->nextPendingConnection();
  83. if (clientSocket == nullptr)
  84. {
  85. SPDLOG_LOGGER_ERROR(m_logger, "Failed to get pending connection.");
  86. return;
  87. }
  88. connect(clientSocket, &QTcpSocket::disconnected, this, &RTPServer::do_disconnect);
  89. connect(clientSocket, &QTcpSocket::readyRead, this, &RTPServer::do_receiveMessage);
  90. SPDLOG_LOGGER_INFO(m_logger, "新的客户端连接: {}", clientSocket->peerAddress().toString().toStdString());
  91. m_listClients.append(clientSocket); // 添加到客户端列表中
  92. }
  93. /* 监听服务错误 */
  94. void RTPServer::do_error(QAbstractSocket::SocketError socketError)
  95. {
  96. SPDLOG_LOGGER_ERROR(m_logger, "RTP Server error: {}, {}", static_cast<int>(socketError), m_tcpServer->errorString().toStdString());
  97. }
  98. /* 断开连接 */
  99. void RTPServer::do_disconnect()
  100. {
  101. QTcpSocket* clientSocket = qobject_cast<QTcpSocket*>(sender());
  102. if (clientSocket)
  103. {
  104. SPDLOG_LOGGER_INFO(m_logger, "客户端断开连接: {}", clientSocket->peerAddress().toString().toStdString());
  105. clientSocket->deleteLater();
  106. m_listClients.removeAll(clientSocket);
  107. } else
  108. {
  109. SPDLOG_LOGGER_ERROR(m_logger, "Failed to cast sender to QTcpSocket.");
  110. }
  111. }
  112. /* 接收消息 */
  113. void RTPServer::do_receiveMessage()
  114. {
  115. QTcpSocket* clientSocket = qobject_cast<QTcpSocket*>(sender());
  116. if (clientSocket == nullptr)
  117. {
  118. SPDLOG_LOGGER_ERROR(m_logger, "Failed to cast sender to QTcpSocket.");
  119. return;
  120. }
  121. QString recvIP = clientSocket->peerAddress().toString();
  122. quint16 recvPort = clientSocket->peerPort();
  123. QByteArray data = clientSocket->readAll();
  124. if (data.isEmpty())
  125. {
  126. SPDLOG_LOGGER_WARN(m_logger, "Received empty data from client: {}", recvIP.toStdString());
  127. return;
  128. }
  129. SPDLOG_LOGGER_TRACE(m_logger, "RTPServer从: {}:{} 接收到原始数据: {}, 大小: {}",
  130. recvIP.toStdString(), recvPort, data.toHex().toStdString(), data.size());
  131. // SPDLOG_LOGGER_TRACE(m_logger, "RTPServer从: {}:{} 接收到数据: {}",
  132. // clientSocket->peerAddress().toString().toStdString(), clientSocket->peerPort(),
  133. // QString(data).toStdString());
  134. // return;
  135. if(static_cast<unsigned long>(data.size()) != sizeof(RtpRecvClientInfo_t))
  136. {
  137. SPDLOG_LOGGER_WARN(m_logger, "从客户端接收到的数据大小: {} 不等于应有的大小 {}", data.size(), sizeof(RtpRecvClientInfo_t));
  138. return;
  139. }
  140. /* 处理接收到的数据 */
  141. RtpSendClientInfo_t sendInfo;
  142. RtpRecvClientInfo_t* recvInfo = reinterpret_cast<RtpRecvClientInfo_t*>(data.data());
  143. SPDLOG_LOGGER_DEBUG(m_logger, "客户端信息: ");
  144. SPDLOG_LOGGER_DEBUG(m_logger, " 客户端IP: {}", recvInfo->clientIP);
  145. SPDLOG_LOGGER_DEBUG(m_logger, " 客户端端口: {}", recvInfo->clientPort);
  146. SPDLOG_LOGGER_DEBUG(m_logger, " 对比项ID: {}", recvInfo->compareItemID);
  147. SPDLOG_LOGGER_DEBUG(m_logger, " 对比项通道号: {}", recvInfo->compareItemRoadNum);
  148. SPDLOG_LOGGER_DEBUG(m_logger, " 包类型: {}", recvInfo->type);
  149. /* 解析客户端发送的信息 */
  150. sendInfo.clientIP = recvInfo->clientIP;
  151. sendInfo.clientPort = recvInfo->clientPort;
  152. // sendInfo.compareItemID = recvInfo->compareItemID;
  153. // sendInfo.compareItemRoadNum = recvInfo->compareItemRoadNum;
  154. /* 根据对比项ID和通道编号查找到使用到的声卡通道编号 */
  155. SoundCardRoadInfo_t roadInfo = CompareItemManager.getSoundCardRoadInfo(recvInfo->compareItemID, recvInfo->compareItemRoadNum);
  156. if(roadInfo.nSoundCardNum < 0 || roadInfo.roadInfo.nRoadNum < 0)
  157. {
  158. SPDLOG_LOGGER_ERROR(m_logger, "无法获取对比项 {} 通道 {} 的声卡信息",
  159. recvInfo->compareItemID, recvInfo->compareItemRoadNum);
  160. return;
  161. }
  162. sendInfo.SoundCardNum = roadInfo.nSoundCardNum;
  163. sendInfo.SoundCardRoadNum = roadInfo.roadInfo.nRoadNum;
  164. switch(recvInfo->type)
  165. {
  166. case 0: // 登录请求
  167. handleLogin(sendInfo);
  168. break;
  169. case 1: // 心跳请求
  170. handleHeartbeat(sendInfo);
  171. break;
  172. case 2: // 注销请求
  173. handleLogout(sendInfo);
  174. break;
  175. default:
  176. SPDLOG_LOGGER_WARN(m_logger, "来自客户端未知的请求:{}, {}:{}", recvInfo->type, sendInfo.clientIP.toStdString(), sendInfo.clientPort);
  177. break;
  178. }
  179. }
  180. /* 一个通道UDP关闭的信号 */
  181. void RTPServer::do_udpClosed(int soundCardNum, int roadNum)
  182. {
  183. SPDLOG_LOGGER_DEBUG(m_logger, "接收到释放本地端口的信号: 声卡编号: {}, 通道编号: {}",
  184. soundCardNum, roadNum);
  185. // for(auto it = m_mapSoundCardRoadPorts.begin(); it != m_mapSoundCardRoadPorts.end(); ++it)
  186. // {
  187. // if(it.key().nSoundCardNum == soundCardNum && it.key().nRoadNum == roadNum)
  188. // {
  189. // // SPDLOG_LOGGER_DEBUG(m_logger, "从声卡通道列表中删除: 声卡编号: {}, 通道编号: {}, 本地端口: {}",
  190. // // soundCardNum, roadNum, localPort);
  191. // m_mapSoundCardRoadPorts.remove(it.key());
  192. // break;
  193. // }
  194. // }
  195. }
  196. /* 处理心跳超时 */
  197. void RTPServer::do_heartbeatTimeout()
  198. {
  199. const QDateTime currentTime = QDateTime::currentDateTime();
  200. QList<RtpClientKey_t> keysToRemove;
  201. for (auto it = m_mapClientHeartbeats.begin(); it != m_mapClientHeartbeats.end(); ++it)
  202. {
  203. if (it.value().secsTo(currentTime) > 20) // 超过30秒未收到心跳
  204. {
  205. SPDLOG_LOGGER_WARN(m_logger, "客户端 {}:{} 心跳超时,准备移除",
  206. it.key().clientIP.toStdString(), it.key().clientPort);
  207. keysToRemove.append(it.key());
  208. }
  209. }
  210. /* 注销超时的会话 */
  211. for (const auto& key : keysToRemove)
  212. {
  213. RtpSendClientInfo_t clientInfo;
  214. clientInfo.clientIP = key.clientIP;
  215. clientInfo.clientPort = key.clientPort;
  216. clientInfo.SoundCardNum = key.SoundCardNum;
  217. clientInfo.SoundCardRoadNum = key.SoundCardRoadNum;
  218. handleLogout(clientInfo);
  219. }
  220. }
  221. /* 处理登录请求 */
  222. void RTPServer::handleLogin(RtpSendClientInfo_t& clientInfo)
  223. {
  224. SPDLOG_LOGGER_TRACE(m_logger, "处理登录请求: {}:{}", clientInfo.clientIP.toStdString(), clientInfo.clientPort);
  225. /* 查找本地可用的UDP端口,这里先使用10010测试 */
  226. // clientInfo.localPort = 10010;
  227. clientInfo.localIP = m_localIP;
  228. /* 查找RTP发送线程 */
  229. auto pThread = ThreadMan.getRtpSendThread(clientInfo.SoundCardNum, clientInfo.SoundCardRoadNum);
  230. if(pThread == nullptr)
  231. {
  232. SPDLOG_LOGGER_ERROR(m_logger, "没有找到对应的RTP发送线程,声卡编号: {}, 通道编号: {}",
  233. clientInfo.SoundCardNum, clientInfo.SoundCardRoadNum);
  234. return;
  235. }
  236. /* 设置客户端信息 */
  237. if(!pThread->addUdpSession(clientInfo))
  238. {
  239. return;
  240. }
  241. connect(pThread, &RTPOneRoadThread::signal_udpClosed, this, &RTPServer::do_udpClosed);
  242. /* 将本地端口添加到心跳列表中 */
  243. RtpClientKey_t clientKey;
  244. clientKey.clientIP = clientInfo.clientIP;
  245. clientKey.clientPort = clientInfo.clientPort;
  246. clientKey.SoundCardNum = clientInfo.SoundCardNum;
  247. clientKey.SoundCardRoadNum = clientInfo.SoundCardRoadNum;
  248. m_mapClientHeartbeats[clientKey] = QDateTime::currentDateTime();
  249. }
  250. /* 处理心跳请求 */
  251. void RTPServer::handleHeartbeat(RtpSendClientInfo_t& clientInfo)
  252. {
  253. SPDLOG_LOGGER_TRACE(m_logger, "处理心跳请求: {}:{}", clientInfo.clientIP.toStdString(), clientInfo.clientPort);
  254. RtpClientKey_t clientKey;
  255. clientKey.clientIP = clientInfo.clientIP;
  256. clientKey.clientPort = clientInfo.clientPort;
  257. clientKey.SoundCardNum = clientInfo.SoundCardNum;
  258. clientKey.SoundCardRoadNum = clientInfo.SoundCardRoadNum;
  259. /* 更新心跳时间 */
  260. if(m_mapClientHeartbeats.contains(clientKey))
  261. {
  262. m_mapClientHeartbeats[clientKey] = QDateTime::currentDateTime();
  263. SPDLOG_LOGGER_TRACE(m_logger, "更新心跳时间: {}:{}", clientInfo.clientIP.toStdString(), clientInfo.clientPort);
  264. }
  265. }
  266. /* 处理注销请求 */
  267. void RTPServer::handleLogout(RtpSendClientInfo_t& clientInfo)
  268. {
  269. SPDLOG_LOGGER_TRACE(m_logger, "处理注销请求: {}:{}", clientInfo.clientIP.toStdString(), clientInfo.clientPort);
  270. /* 查找RTP发送线程 */
  271. auto pThread = ThreadMan.getRtpSendThread(clientInfo.SoundCardNum, clientInfo.SoundCardRoadNum);
  272. if(pThread == nullptr)
  273. {
  274. SPDLOG_LOGGER_ERROR(m_logger, "没有找到对应的RTP发送线程,声卡编号: {}, 通道编号: {}",
  275. clientInfo.SoundCardNum, clientInfo.SoundCardRoadNum);
  276. return;
  277. }
  278. /* 删除UDP会话 */
  279. if(!pThread->removeUdpSession(clientInfo.clientIP, clientInfo.clientPort))
  280. {
  281. SPDLOG_LOGGER_ERROR(m_logger, "删除UDP会话失败: {}:{}", clientInfo.clientIP.toStdString(), clientInfo.clientPort);
  282. return;
  283. }
  284. /* 将客户端信息从心跳列表中移除 */
  285. RtpClientKey_t clientKey;
  286. clientKey.clientIP = clientInfo.clientIP;
  287. clientKey.clientPort = clientInfo.clientPort;
  288. clientKey.SoundCardNum = clientInfo.SoundCardNum;
  289. clientKey.SoundCardRoadNum = clientInfo.SoundCardRoadNum;
  290. if(m_mapClientHeartbeats.contains(clientKey))
  291. {
  292. m_mapClientHeartbeats.remove(clientKey);
  293. SPDLOG_LOGGER_DEBUG(m_logger, "从心跳列表中移除客户端: {}:{}",
  294. clientInfo.clientIP.toStdString(), clientInfo.clientPort);
  295. }
  296. }
  297. /* 查找本地出口IP,适用于单个出口IP,如果电脑上有多个网口,需要手动指定IP */
  298. QString RTPServer::findLocalIP()
  299. {
  300. QString localIP;
  301. QList<QHostAddress> addresses = QNetworkInterface::allAddresses();
  302. for (const QHostAddress& address : addresses)
  303. {
  304. if (address.protocol() == QAbstractSocket::IPv4Protocol && !address.isLoopback())
  305. {
  306. if(address == QHostAddress::AnyIPv4)
  307. {
  308. continue; // 跳过
  309. }
  310. localIP = address.toString();
  311. SPDLOG_LOGGER_INFO(m_logger, "找到本地出口IP: {}", localIP.toStdString());
  312. return localIP;
  313. }
  314. }
  315. SPDLOG_LOGGER_ERROR(m_logger, "未找到有效的本地出口IP");
  316. return localIP;
  317. }