123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418 |
- /*
- * udp_client.cpp
- *
- * Created on: 2023年4月17日
- * Author: m
- */
- #include "udp_client.h"
- #include <system/Thread.h>
- #include <string>
- #include <chrono>
- #include "entry/EasyuiContext.h"
- #include "utils/Log.h"
- #include "utils/ByteUtil.h"
- #include "base/os.hpp"
- #include "base/strings.hpp"
- #include "net/NetManager.h"
- #include "service/BusinessConfig.h"
- #include "core/utilities.h"
- #define ETHERNETMANAGER NETMANAGER->getEthernetManager()
- #define WIFIMANAGER NETMANAGER->getWifiManager()
- #define DISCOVERY_PORT 8031
- #define DISCOVERY_TIMEOUT 10
- #define CONNECTION_TIMEOUT 120
- void udpHandleMsg(byte* msg);
- UdpClient::UdpClient() {
- busy_ = false;
- }
- UdpClient::~UdpClient() {
- }
- UdpClient* UdpClient::instance() {
- static UdpClient singleton;
- return &singleton;
- }
- static net::Conn* discover_conn;
- static net::Conn* conn;
- void UdpClient::sendMsg(const char* msg){
- instance()->internalSendMsg(msg, conn);
- }
- void UdpClient::sendMsg(const char* msg, net::Conn* _conn){
- instance()->internalSendMsg(msg, conn);
- }
- void UdpClient::internalSendMsg(const char* msg, net::Conn* _conn) {
- if (busy_) {
- LOGD("udp client is busy");
- return;
- }
- busy_ = true;
- std::string endDelimiter = "#END#";
- std::string msgStr = msg + endDelimiter;
- const char* sendMsg = msgStr.c_str();
- if (_conn){
- _conn->Write((byte*)(sendMsg), strlen(sendMsg));
- LOGD("udp sended msg : %s",sendMsg);
- } else {
- LOGD("udp disconnect");
- }
- busy_ = false;
- }
- int ip4str_parse(const char *point, unsigned int result[4]) {
- for (int i = 0; i < 4; i++) {
- result[i] = 0;
- }
- char buf[18] = {0}, p = 0, q = 0;
- strcpy(buf, point);
- buf[strlen(point)] = '.';
- for(int i = 0;i < 4; i++) {
- q = strchr(buf+p, '.') - buf;
- buf[q] = '\0';
- result[i] = strtol(buf+p, NULL, 10);
- p = q + 1;
- }
- return 1;
- }
- char ip[64] = {0};
- char mask[64] = {0};
- char gateway[64] = {0};
- char dns1[64] = {0};
- char dns2[64] = {0};
- std::string getBoasrAddress() {
- if (ETHERNETMANAGER->isConnected()) {
- if (ETHERNETMANAGER->isAutoMode()) {
- ETHERNETMANAGER->getConfigureInfo(ip, mask, gateway, dns1, dns2);
- } else {
- ETHERNETMANAGER->getStaticConfigureInfo(ip, mask, gateway, dns1, dns2);
- }
- }
- else if (WIFIMANAGER->isConnected()) {
- WIFIMANAGER->getConfigureInfo(ip, mask, gateway, dns1, dns2);
- // if (WIFIMANAGER->isAutoMode()) {
- // WIFIMANAGER->getConfigureInfo(ip, mask, gateway, dns1, dns2);
- // }
- // else {
- // WIFIMANAGER->getConfigureInfo(ip, mask, gateway, dns1, dns2);
- // }
- }
- unsigned int ipAdd[4];
- unsigned int maskAdd[4];
- ip4str_parse(ip, ipAdd);
- ip4str_parse(mask, maskAdd);
- int wilMask[4];
- int startIpAdd[4],endIpAdd[4];
- for (int i = 0; i < 4; i++) {
- wilMask[i] = 255 - maskAdd[i];
- }
- for (int i = 0; i < 4; i++) {
- startIpAdd[i] = ipAdd[i] & maskAdd[i];
- endIpAdd[i] = startIpAdd[i] + wilMask[i];
- }
- std::string boasrAddress = std::to_string(endIpAdd[0]) + "." + std::to_string(endIpAdd[1]) + "." + std::to_string(endIpAdd[2]) + "." + std::to_string(endIpAdd[3]) + ":" + std::to_string(DISCOVERY_PORT);
- return boasrAddress;
- }
- class UdpClientThread: public Thread {
- private:
- enum State {
- STATE_DISCOVERING, // 正在广播探测
- STATE_CONNECTED, // 已连接服务器
- STATE_DISCONNECT, // 服务器断开
- };
- inline static std::string REQUEST = "REQUEST";
- inline static std::string RESPONSE = "RESPONSE";
- inline static std::string CONNECT = "CONNECT";
- inline static std::string DISCONNECT = "DISCONNECT";
- inline static std::string RECONNECT = "RECONNECT";
- std::atomic<State> current_state_{STATE_DISCOVERING};
- std::string server_ip_; // 服务器地址缓存
- std::string server_port_; // 服务器端口
- bool send(net::Conn* _conn, const std::string msg) {
- // 构造消息字符串
- std::string endDelimiter = "#END#";
- std::string msgStr = msg + endDelimiter;
- const char* sendMsg = msgStr.data();
- if (_conn){
- _conn->Write((byte*)(sendMsg), strlen(sendMsg));
- LOGD("向udp服务器发送消息 : %s", sendMsg);
- return true;
- }
- LOGD("udp disconnect");
- return false;
- }
- void requestUdpServerIp(net::Conn* _conn) {
- Json::Value reqJson;
- reqJson["action"] = REQUEST;
- Json::FastWriter writer;
- const std::string req = writer.write(reqJson);
- send(_conn, req);
- }
- void sendDeviceMsg(net::Conn* _conn) {
- Json::Value reqJson;
- reqJson["action"] = CONNECT;
- reqJson["ip"] = ip;
- reqJson["mac"] = StoragePreferences::getString(STORE_MAC_ADDR, "0.0.0.0");
- reqJson["gateway"] = gateway;
- reqJson["mask"] = mask;
- reqJson["version"] = versionCode + "_" + std::to_string(versionNo);
- reqJson["id"] = StoragePreferences::getInt(STORE_DEVICE_ID, 0);
- reqJson["partId"] = StoragePreferences::getString(STORE_PARTID, "");
- reqJson["partName"] = StoragePreferences::getString(STORE_PARTNAME, "");
- reqJson["frameName"] = StoragePreferences::getString(STORE_FRAME_FULL_NAME, "");
- Json::FastWriter writer;
- const std::string req = writer.write(reqJson);
- send(_conn, req);
- }
- void handleDiscoveryState() {
- LOGD("进入广播探测状态");
- using Clock = std::chrono::steady_clock;
- constexpr auto TIMEOUT = std::chrono::seconds(60);
- auto start_time = Clock::now();
- // 设置一个默认地址
- std::string boasrAddress = "172.28.100.100:" + std::to_string(DISCOVERY_PORT);
- if (ETHERNETMANAGER->isConnected() || WIFIMANAGER->isConnected()) {
- boasrAddress = getBoasrAddress();
- }
- LOGD("UDP广播地址 ===> %s", boasrAddress.c_str());
- discover_conn = net::Dial("udp", boasrAddress);
- if (!discover_conn) {
- current_state_ = STATE_DISCONNECT;
- LOGD("UDP广播连接失败,udp断开");
- return;
- }
- requestUdpServerIp(discover_conn);
- byte buf[2048] = {0};
- bool server_found = false;
- while (true) {
- auto elapsed = Clock::now() - start_time;
- if (elapsed >= TIMEOUT) break;
- //读取,超时1000毫秒
- int n = discover_conn->Read(buf, sizeof(buf) - 1, 1000);
- if (n > 0) {
- Json::Value jsonData = ByteUtil::byteArrayToJson(buf, n);
- if (!jsonData.isNull() && jsonData.isMember("action")) {
- if (jsonData["action"] == RESPONSE) {
- server_ip_ = jsonData["ip"].asString();
- server_port_ = jsonData["port"].asString();
- LOGD("udp广播服务器的地址 ===> %s:%s", server_ip_.c_str(), server_port_.c_str());
- server_found = true;
- break;
- }
- }
- }
- }
- //关闭连接
- discover_conn->Close();
- //释放内存
- delete discover_conn;
- discover_conn = NULL;
- if (server_found) {
- current_state_ = STATE_CONNECTED;
- LOGD("收到udp服务器地址消息,切换到udp服务连接");
- }
- else {
- current_state_ = STATE_DISCONNECT;
- LOGD("未收到udp服务器地址消息,断开udp");
- }
- }
- void handleConnectedState() {
- LOGD("进入连接状态");
- using namespace std::chrono;
- using Clock = steady_clock;
- std::string serverAddr = server_ip_ + ":" + server_port_;
- LOGD("定向连接udp服务器 ===> %s", serverAddr.c_str());
- // 创建定向连接
- conn = net::Dial("udp", serverAddr);
- if (!conn) {
- current_state_ = STATE_DISCONNECT;
- LOGD("UDP定向连接失败,udp断开");
- return;
- }
- sendDeviceMsg(conn);
- constexpr auto TIMEOUT = std::chrono::seconds(120);
- constexpr auto HEARTBEAT = std::chrono::seconds(60);
- auto last_recv_time = Clock::now();
- auto last_heartbeat = Clock::now();
- auto connection_start = Clock::now();
- // 通信循环
- byte buffer[2048];
- bool should_disconnect = false;
- while (!exitPending() && !should_disconnect) {
- auto time_since_last = steady_clock::now() - last_recv_time;
- if (time_since_last > TIMEOUT) {
- LOGD("连接超时(已等待%lld秒)", time_since_last.count());
- should_disconnect = true;
- break;
- }
- auto time_since_heartbeat = steady_clock::now() - last_heartbeat;
- if (time_since_heartbeat >= HEARTBEAT) {
- const std::string msg = "0";
- send(conn, msg);
- }
- // 动态计算本次读操作的超时时间(毫秒)
- auto remaining = duration_cast<milliseconds>(
- TIMEOUT - time_since_last
- );
- // 接收数据
- int n = conn->Read(buffer, sizeof(buffer)-1, 1000);
- if (n > 0) {
- last_recv_time = Clock::now(); // 更新最后有效接收时间
- const char* cstr = reinterpret_cast<const char*>(buffer);
- std::string str = cstr;
- if (str == "1#END#"){
- last_heartbeat = Clock::now();
- continue;
- }
- LOGD("收到定向udp服务返回消息 ===> %s", cstr);
- Json::Value jsonData = ByteUtil::byteArrayToJson(buffer, n);
- if (!jsonData.isNull() && jsonData.isMember("action")) {
- if (jsonData["action"] == DISCONNECT) {
- // 退出线程
- should_disconnect = true;
- current_state_ = STATE_DISCONNECT;
- break;
- }
- else if (jsonData["action"] == RECONNECT) {
- sendDeviceMsg(conn);
- }
- }
- // handleServerMessage(buffer); // 处理业务消息
- } else if (n < 0 && n != net::E_TIMEOUT) {
- should_disconnect = true;
- current_state_ = STATE_DISCONNECT;
- break; // 发生错误
- }
- }
- // 计算总连接时长
- auto total_duration = steady_clock::now() - connection_start;
- LOGD("连接持续时间: %lld 秒", total_duration.count());
- // 清理连接
- conn->Close();
- delete conn;
- conn = NULL;
- current_state_ = STATE_DISCONNECT;
- }
- public:
- /**
- * 线程创建成功后会调用该函数,可以在该函数中做一些初始化操作
- * return true 继续线程
- * false 退出线程
- */
- virtual bool readyToRun() {
- LOGD("Udp Thread 已经创建完成");
- return true;
- }
- /**
- * 线程循环函数
- *
- * return true 继续线程循环
- * false 推出线程
- */
- virtual bool threadLoop() {
- LOGD("Udp 线程循环函数");
- //检查是否有退出线程的请求,如果有,则返回false,立即退出线程
- if (exitPending()) {
- LOGD("Udp exitPending");
- return false;
- }
- switch (current_state_) {
- case STATE_DISCOVERING:
- handleDiscoveryState();
- break;
- case STATE_CONNECTED:
- handleConnectedState();
- break;
- case STATE_DISCONNECT:
- return false;
- break;
- }
- return true;
- }
- };
- static UdpClientThread udp_thread;
- void UdpClient::startUdp(){
- LOGD("运行Udp线程");
- //调用线程类的run函数启动线程, 参数为线程名,可以任意指定。
- if (!udp_thread.isRunning()) {
- udp_thread.run("udp thread");
- }
- }
- void UdpClient::closeUdp() {
- bool result = udp_thread.isRunning();
- if (result) {
- udp_thread.requestExitAndWait();
- LOGD("my_thread已关闭");
- }
- // my_thread.requestExit();
- }
- bool UdpClient::busy() {
- return instance()->busy_;
- }
- bool UdpClient::connected() {
- return conn != NULL || discover_conn != NULL;
- }
|