UDPServer.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. #include "UDPServer.h"
  2. UDPServer::~UDPServer() {
  3. socket_->close();
  4. }
  5. void UDPServer::init_socket()
  6. {
  7. static std::mutex init_mutex;
  8. std::lock_guard<std::mutex> lock(init_mutex);
  9. // 确保 io_context 没有在运行
  10. if (!io_context_.stopped()) {
  11. // 暂停 io_context
  12. io_context_.stop();
  13. std::this_thread::sleep_for(std::chrono::milliseconds(10));
  14. }
  15. // 创建 socket
  16. socket_ = std::make_unique<udp::socket>(io_context_);
  17. // 绑定端口
  18. asio::error_code ec;
  19. socket_->open(udp::v4(), ec);
  20. if (!ec) {
  21. socket_->bind(udp::endpoint(udp::v4(), nPort_), ec);
  22. }
  23. if (ec) {
  24. LOG_ERROR("Failed to bind socket: " + ec.message());
  25. socket_.reset();
  26. return;
  27. }
  28. // 重启 io_context
  29. io_context_.restart();
  30. // 开始接收
  31. start_receive();
  32. }
  33. void UDPServer::setCMDQueue(HDDSCMDQueue* pQueue) {
  34. m_pCMDQueue = pQueue;
  35. }
  36. void UDPServer::setSendParam(const char* hostIP, int nPort)
  37. {
  38. // 延迟创建resolver
  39. if (!resolver_) {
  40. resolver_ = std::make_unique<udp::resolver>(io_context_);
  41. }
  42. char cPort[30];
  43. snprintf(cPort, sizeof(cPort), "%d", nPort);
  44. endpoint_ = resolver_->resolve(udp::v4(), hostIP, cPort);
  45. }
  46. void UDPServer::start_receive() {
  47. socket_->async_receive_from(
  48. asio::buffer(data, max_length),
  49. remote_endpoint_,
  50. [this](std::error_code ec, std::size_t bytes_recvd) {
  51. this->handle_receive(ec, bytes_recvd);
  52. }
  53. );
  54. }
  55. void UDPServer::handle_receive(std::error_code ec, std::size_t bytes_recvd) {
  56. if (!ec && bytes_recvd > 0) {
  57. HDDSCMD pCMD;
  58. if (bytes_recvd <= sizeof(HDDSCMD)) {
  59. memcpy(&pCMD, data, sizeof(HDDSCMD));
  60. if (m_pCMDQueue) {
  61. m_pCMDQueue->push(pCMD);
  62. }
  63. }
  64. else {
  65. LOG_WARNING("Received data too small for HDDSCMD structure");
  66. }
  67. }
  68. else if (ec) {
  69. LOG_ERROR("Receive error: " + ec.message());
  70. }
  71. start_receive();
  72. }
  73. int UDPServer::blockingSendData(LPHDDSCMD pData, long DataLen) {
  74. if (DataLen > max_length + 12) {
  75. LOG_WARNING("Data too large to send");
  76. return -1;
  77. }
  78. memcpy(sendData, pData, DataLen);
  79. try {
  80. return socket_->send_to(asio::buffer(sendData, DataLen), *endpoint_.begin());
  81. }
  82. catch (std::exception& e) {
  83. LOG_ERROR("Send error: " + std::string(e.what()));
  84. return -1;
  85. }
  86. }
  87. int UDPServer::asyncSendData(LPHDDSCMD pData, long DataLen) {
  88. // 异步发送实现
  89. return 1;
  90. }
  91. // 解析单个目标地址
  92. bool UDPServer::resolveTarget(UDPTarget& target) {
  93. if (!resolver_) {
  94. resolver_ = std::make_unique<udp::resolver>(io_context_);
  95. }
  96. try {
  97. char cPort[30];
  98. snprintf(cPort, sizeof(cPort), "%d", target.port);
  99. auto endpoints = resolver_->resolve(udp::v4(), target.ip, cPort);
  100. if (endpoints.begin() != endpoints.end()) {
  101. target.endpoint = *endpoints.begin();
  102. target.resolved = true;
  103. return true;
  104. }
  105. }
  106. catch (const std::exception& e) {
  107. LOG_ERROR("Failed to resolve target " + target.ip + ":" +
  108. std::to_string(target.port) + " - " + std::string(e.what()));
  109. }
  110. return false;
  111. }
  112. // 解析所有未解析的目标
  113. void UDPServer::resolveAllTargets() {
  114. std::lock_guard<std::mutex> lock(targets_mutex_);
  115. for (auto& target : multi_targets_) {
  116. if (!target.resolved) {
  117. resolveTarget(target);
  118. }
  119. }
  120. }
  121. // 新增接口:设置多个目标
  122. void UDPServer::setMultiSendParams(const std::vector<UDPTarget>& targets) {
  123. std::lock_guard<std::mutex> lock(targets_mutex_);
  124. multi_targets_.clear();
  125. multi_targets_ = targets;
  126. // 解析所有目标地址
  127. resolveAllTargets();
  128. LOG_INFO("Set " + std::to_string(multi_targets_.size()) + " multi-targets");
  129. }
  130. void UDPServer::addSendTarget(const char* hostIP, int nPort) {
  131. std::lock_guard<std::mutex> lock(targets_mutex_);
  132. // 检查是否已存在
  133. for (const auto& target : multi_targets_) {
  134. if (target.ip == hostIP && target.port == nPort) {
  135. LOG_WARNING("Target already exists: " + std::string(hostIP) + ":" + std::to_string(nPort));
  136. return;
  137. }
  138. }
  139. // 添加新目标
  140. UDPTarget new_target;
  141. new_target.ip = hostIP;
  142. new_target.port = nPort;
  143. new_target.resolved = false;
  144. // 立即解析
  145. if (resolveTarget(new_target)) {
  146. multi_targets_.push_back(new_target);
  147. LOG_INFO("Added target: " + std::string(hostIP) + ":" + std::to_string(nPort));
  148. }
  149. else {
  150. LOG_ERROR("Failed to add target: " + std::string(hostIP) + ":" + std::to_string(nPort));
  151. }
  152. }
  153. void UDPServer::removeSendTarget(const char* hostIP, int nPort) {
  154. std::lock_guard<std::mutex> lock(targets_mutex_);
  155. auto it = std::remove_if(multi_targets_.begin(), multi_targets_.end(),
  156. [hostIP, nPort](const UDPTarget& target) {
  157. return target.ip == hostIP && target.port == nPort;
  158. });
  159. if (it != multi_targets_.end()) {
  160. multi_targets_.erase(it, multi_targets_.end());
  161. LOG_INFO("Removed target: " + std::string(hostIP) + ":" + std::to_string(nPort));
  162. }
  163. else {
  164. LOG_WARNING("Target not found: " + std::string(hostIP) + ":" + std::to_string(nPort));
  165. }
  166. }
  167. void UDPServer::clearSendTargets() {
  168. std::lock_guard<std::mutex> lock(targets_mutex_);
  169. multi_targets_.clear();
  170. LOG_INFO("Cleared all send targets");
  171. }
  172. int UDPServer::blockingSendDataToMulti(LPHDDSCMD pData, long DataLen)
  173. {
  174. if (DataLen > max_length + 12) {
  175. LOG_WARNING("Data too large to send");
  176. return -1;
  177. }
  178. std::lock_guard<std::mutex> lock(targets_mutex_);
  179. if (multi_targets_.empty()) {
  180. LOG_WARNING("No multi-targets set");
  181. return 0;
  182. }
  183. memcpy(sendData, pData, DataLen);
  184. int total_sent = 0;
  185. int success_count = 0;
  186. for (const auto& target : multi_targets_) {
  187. if (target.resolved) {
  188. try {
  189. int sent = socket_->send_to(asio::buffer(sendData, DataLen), target.endpoint);
  190. total_sent += sent;
  191. success_count++;
  192. }
  193. catch (std::exception& e) {
  194. LOG_ERROR("Send to " + target.ip + ":" + std::to_string(target.port) +
  195. " error: " + std::string(e.what()));
  196. }
  197. }
  198. else {
  199. LOG_WARNING("Target not resolved: " + target.ip + ":" + std::to_string(target.port));
  200. }
  201. }
  202. LOG_INFO("Sent to " + std::to_string(success_count) + "/" +
  203. std::to_string(multi_targets_.size()) + " targets");
  204. return total_sent;
  205. }
  206. // 新增接口:异步发送到多个目标
  207. int UDPServer::asyncSendDataToMulti(LPHDDSCMD pData, long DataLen) {
  208. if (DataLen > max_length + 12) {
  209. LOG_WARNING("Data too large to send");
  210. return -1;
  211. }
  212. std::lock_guard<std::mutex> lock(targets_mutex_);
  213. if (multi_targets_.empty()) {
  214. LOG_WARNING("No multi-targets set");
  215. return 0;
  216. }
  217. // 复制数据到新缓冲区,确保在异步发送期间有效
  218. auto send_buffer = std::make_shared<std::vector<char>>(DataLen);
  219. memcpy(send_buffer->data(), pData, DataLen);
  220. int success_count = 0;
  221. for (const auto& target : multi_targets_) {
  222. if (target.resolved) {
  223. try {
  224. socket_->async_send_to(
  225. asio::buffer(*send_buffer),
  226. target.endpoint,
  227. [this, send_buffer, target](std::error_code ec, std::size_t bytes_sent) {
  228. if (!ec) {
  229. LOG_INFO("Async sent " + std::to_string(bytes_sent) +
  230. " bytes to " + target.ip + ":" + std::to_string(target.port));
  231. }
  232. else {
  233. LOG_ERROR("Async send to " + target.ip + ":" + std::to_string(target.port) +
  234. " error: " + ec.message());
  235. }
  236. }
  237. );
  238. success_count++;
  239. }
  240. catch (std::exception& e) {
  241. LOG_ERROR("Async send to " + target.ip + ":" + std::to_string(target.port) +
  242. " error: " + std::string(e.what()));
  243. }
  244. }
  245. else {
  246. LOG_WARNING("Target not resolved: " + target.ip + ":" + std::to_string(target.port));
  247. }
  248. }
  249. LOG_INFO("Async sending to " + std::to_string(success_count) + "/" +
  250. std::to_string(multi_targets_.size()) + " targets");
  251. return success_count;
  252. }