RtpServer.cpp 13 KB

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