RtpServer.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  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. /* 开启事件循环 */
  53. connect(m_tcpServer, &QTcpServer::newConnection, this, &RTPServer::do_newConnection);
  54. connect(m_tcpServer, &QTcpServer::acceptError, this, &RTPServer::do_error);
  55. m_isStoped.store(false);
  56. m_eventLoop.exec();
  57. m_isStoped.store(true);
  58. SPDLOG_LOGGER_INFO(m_logger, "♫ RTPServer 线程结束运行");
  59. return true;
  60. }
  61. /* 停止线程 */
  62. void RTPServer::stopThreadBlock()
  63. {
  64. if(m_eventLoop.isRunning())
  65. {
  66. m_eventLoop.quit();
  67. }
  68. while(!m_isStoped.load())
  69. {
  70. std::this_thread::sleep_for(std::chrono::milliseconds(10));
  71. }
  72. }
  73. /* 处理新连接 */
  74. void RTPServer::do_newConnection()
  75. {
  76. QTcpSocket* clientSocket = m_tcpServer->nextPendingConnection();
  77. if (clientSocket == nullptr)
  78. {
  79. SPDLOG_LOGGER_ERROR(m_logger, "Failed to get pending connection.");
  80. return;
  81. }
  82. connect(clientSocket, &QTcpSocket::disconnected, this, &RTPServer::do_disconnect);
  83. connect(clientSocket, &QTcpSocket::readyRead, this, &RTPServer::do_receiveMessage);
  84. SPDLOG_LOGGER_INFO(m_logger, "新的客户端连接: {}", clientSocket->peerAddress().toString().toStdString());
  85. m_listClients.append(clientSocket); // 添加到客户端列表中
  86. }
  87. /* 监听服务错误 */
  88. void RTPServer::do_error(QAbstractSocket::SocketError socketError)
  89. {
  90. SPDLOG_LOGGER_ERROR(m_logger, "RTP Server error: {}, {}", static_cast<int>(socketError), m_tcpServer->errorString().toStdString());
  91. }
  92. /* 断开连接 */
  93. void RTPServer::do_disconnect()
  94. {
  95. QTcpSocket* clientSocket = qobject_cast<QTcpSocket*>(sender());
  96. if (clientSocket)
  97. {
  98. SPDLOG_LOGGER_INFO(m_logger, "客户端断开连接: {}", clientSocket->peerAddress().toString().toStdString());
  99. clientSocket->deleteLater();
  100. m_listClients.removeAll(clientSocket);
  101. } else
  102. {
  103. SPDLOG_LOGGER_ERROR(m_logger, "Failed to cast sender to QTcpSocket.");
  104. }
  105. }
  106. /* 接收消息 */
  107. void RTPServer::do_receiveMessage()
  108. {
  109. QTcpSocket* clientSocket = qobject_cast<QTcpSocket*>(sender());
  110. if (clientSocket == nullptr)
  111. {
  112. SPDLOG_LOGGER_ERROR(m_logger, "Failed to cast sender to QTcpSocket.");
  113. return;
  114. }
  115. QString recvIP = clientSocket->peerAddress().toString();
  116. quint16 recvPort = clientSocket->peerPort();
  117. QByteArray data = clientSocket->readAll();
  118. if (data.isEmpty())
  119. {
  120. SPDLOG_LOGGER_WARN(m_logger, "Received empty data from client: {}", recvIP.toStdString());
  121. return;
  122. }
  123. SPDLOG_LOGGER_TRACE(m_logger, "RTPServer从: {}:{} 接收到原始数据: {}, 大小: {}",
  124. recvIP.toStdString(), recvPort, data.toHex().toStdString(), data.size());
  125. // SPDLOG_LOGGER_TRACE(m_logger, "RTPServer从: {}:{} 接收到数据: {}",
  126. // clientSocket->peerAddress().toString().toStdString(), clientSocket->peerPort(),
  127. // QString(data).toStdString());
  128. // return;
  129. if(static_cast<unsigned long>(data.size()) < sizeof(RtpRecvClientInfo_t))
  130. {
  131. SPDLOG_LOGGER_WARN(m_logger, "从客户端接收到的数据大小: {} 低于应有的大小 {}",
  132. data.size(), sizeof(RtpRecvClientInfo_t));
  133. return;
  134. }
  135. /* 处理接收到的数据 */
  136. RtpSendClientInfo_t sendInfo;
  137. RtpRecvClientInfo_t* recvInfo = reinterpret_cast<RtpRecvClientInfo_t*>(data.data());
  138. SPDLOG_LOGGER_DEBUG(m_logger, "客户端信息: ");
  139. SPDLOG_LOGGER_DEBUG(m_logger, " 客户端IP: {}", recvInfo->clientIP);
  140. SPDLOG_LOGGER_DEBUG(m_logger, " 客户端端口: {}", recvInfo->clientPort);
  141. SPDLOG_LOGGER_DEBUG(m_logger, " 对比项ID: {}", recvInfo->compareItemID);
  142. SPDLOG_LOGGER_DEBUG(m_logger, " 对比项通道号: {}", recvInfo->compareItemRoadNum);
  143. SPDLOG_LOGGER_DEBUG(m_logger, " 客户端名称: {}", recvInfo->sessionName);
  144. SPDLOG_LOGGER_DEBUG(m_logger, " 包类型: {}", recvInfo->type);
  145. /* 解析客户端发送的信息 */
  146. sendInfo.clientIP = recvInfo->clientIP;
  147. sendInfo.clientPort = recvInfo->clientPort;
  148. sendInfo.compareItemID = recvInfo->compareItemID;
  149. sendInfo.compareItemRoadNum = recvInfo->compareItemRoadNum;
  150. /* 根据对比项ID和通道编号查找到使用到的声卡通道编号 */
  151. SoundCardRoadInfo_t roadInfo = CompareItemManager.getSoundCardRoadInfo(sendInfo.compareItemID, sendInfo.compareItemRoadNum);
  152. if(roadInfo.nSoundCardNum < 0 || roadInfo.roadInfo.nRoadNum < 0)
  153. {
  154. SPDLOG_LOGGER_ERROR(m_logger, "无法获取对比项 {} 通道 {} 的声卡信息",
  155. sendInfo.compareItemID, sendInfo.compareItemRoadNum);
  156. return;
  157. }
  158. sendInfo.SoundCardNum = roadInfo.nSoundCardNum;
  159. sendInfo.SoundCardRoadNum = roadInfo.roadInfo.nRoadNum;
  160. switch(recvInfo->type)
  161. {
  162. case 0: // 登录请求
  163. handleLogin(sendInfo);
  164. break;
  165. case 1: // 心跳请求
  166. handleHeartbeat(sendInfo);
  167. break;
  168. case 2: // 注销请求
  169. handleLogout(sendInfo);
  170. break;
  171. default:
  172. SPDLOG_LOGGER_WARN(m_logger, "来自客户端未知的请求:{}, {}:{}", recvInfo->type, sendInfo.clientIP.toStdString(), sendInfo.clientPort);
  173. break;
  174. }
  175. }
  176. /* 接收到释放端口的信号 */
  177. void RTPServer::do_udpClosed(int soundCardNum, int roadNum, int localPort)
  178. {
  179. SPDLOG_LOGGER_DEBUG(m_logger, "接收到释放本地端口的信号: 声卡编号: {}, 通道编号: {}, 本地端口: {}",
  180. soundCardNum, roadNum, localPort);
  181. for(auto it = m_mapSoundCardRoadPorts.begin(); it != m_mapSoundCardRoadPorts.end(); ++it)
  182. {
  183. if(it.key().nSoundCardNum == soundCardNum && it.key().nRoadNum == roadNum)
  184. {
  185. // SPDLOG_LOGGER_DEBUG(m_logger, "从声卡通道列表中删除: 声卡编号: {}, 通道编号: {}, 本地端口: {}",
  186. // soundCardNum, roadNum, localPort);
  187. m_mapSoundCardRoadPorts.remove(it.key());
  188. break;
  189. }
  190. }
  191. }
  192. /* 处理登录请求 */
  193. void RTPServer::handleLogin(RtpSendClientInfo_t& clientInfo)
  194. {
  195. SPDLOG_LOGGER_TRACE(m_logger, "处理登录请求: {}:{}", clientInfo.clientIP.toStdString(), clientInfo.clientPort);
  196. /* 查找本地可用的UDP端口,这里先使用10010测试 */
  197. clientInfo.localPort = 10010;
  198. clientInfo.localIP = m_localIP;
  199. /* 查找RTP发送线程 */
  200. auto pThread = ThreadMan.getRtpSendThread(clientInfo.SoundCardNum, clientInfo.SoundCardRoadNum);
  201. if(pThread == nullptr)
  202. {
  203. SPDLOG_LOGGER_ERROR(m_logger, "没有找到对应的RTP发送线程,声卡编号: {}, 通道编号: {}",
  204. clientInfo.SoundCardNum, clientInfo.SoundCardRoadNum);
  205. return;
  206. }
  207. /* 设置客户端信息 */
  208. if(!pThread->addUdpSession(clientInfo))
  209. {
  210. return;
  211. }
  212. connect(pThread, &RTPOneRoadThread::signal_udpClosed, this, &RTPServer::do_udpClosed);
  213. /* 将本地端口添加到声卡通道列表中 */
  214. for(auto it = m_mapSoundCardRoadPorts.begin(); it != m_mapSoundCardRoadPorts.end(); ++it)
  215. {
  216. if(it.key().nSoundCardNum == clientInfo.SoundCardNum && it.key().nRoadNum == clientInfo.SoundCardRoadNum)
  217. {
  218. return;
  219. }
  220. }
  221. SoundCardRoadKey_t roadInfo;
  222. roadInfo.nSoundCardNum = clientInfo.SoundCardNum;
  223. roadInfo.nRoadNum = clientInfo.SoundCardRoadNum;
  224. m_mapSoundCardRoadPorts.insert(roadInfo, clientInfo.localPort);
  225. }
  226. /* 处理心跳请求 */
  227. void RTPServer::handleHeartbeat(RtpSendClientInfo_t& clientInfo)
  228. {
  229. SPDLOG_LOGGER_TRACE(m_logger, "处理心跳请求: {}:{}", clientInfo.clientIP.toStdString(), clientInfo.clientPort);
  230. }
  231. /* 处理注销请求 */
  232. void RTPServer::handleLogout(RtpSendClientInfo_t& clientInfo)
  233. {
  234. SPDLOG_LOGGER_TRACE(m_logger, "处理注销请求: {}:{}", clientInfo.clientIP.toStdString(), clientInfo.clientPort);
  235. /* 查找RTP发送线程 */
  236. auto pThread = ThreadMan.getRtpSendThread(clientInfo.SoundCardNum, clientInfo.SoundCardRoadNum);
  237. if(pThread == nullptr)
  238. {
  239. SPDLOG_LOGGER_ERROR(m_logger, "没有找到对应的RTP发送线程,声卡编号: {}, 通道编号: {}",
  240. clientInfo.SoundCardNum, clientInfo.SoundCardRoadNum);
  241. return;
  242. }
  243. /* 删除UDP会话 */
  244. if(!pThread->removeUdpSession(clientInfo.clientIP, clientInfo.clientPort))
  245. {
  246. SPDLOG_LOGGER_ERROR(m_logger, "删除UDP会话失败: {}:{}", clientInfo.clientIP.toStdString(), clientInfo.clientPort);
  247. return;
  248. }
  249. }
  250. /* 查找本地出口IP,适用于单个出口IP,如果电脑上有多个网口,需要手动指定IP */
  251. QString RTPServer::findLocalIP()
  252. {
  253. QString localIP;
  254. QList<QHostAddress> addresses = QNetworkInterface::allAddresses();
  255. for (const QHostAddress& address : addresses)
  256. {
  257. if (address.protocol() == QAbstractSocket::IPv4Protocol && !address.isLoopback())
  258. {
  259. if(address == QHostAddress::AnyIPv4)
  260. {
  261. continue; // 跳过
  262. }
  263. localIP = address.toString();
  264. SPDLOG_LOGGER_INFO(m_logger, "找到本地出口IP: {}", localIP.toStdString());
  265. return localIP;
  266. }
  267. }
  268. SPDLOG_LOGGER_ERROR(m_logger, "未找到有效的本地出口IP");
  269. return localIP;
  270. }