|
@@ -7,12 +7,15 @@
|
|
|
|
|
|
#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 <system/Thread.h>
|
|
|
-#include <string>
|
|
|
#include "net/NetManager.h"
|
|
|
#include "service/BusinessConfig.h"
|
|
|
#include "core/utilities.h"
|
|
@@ -20,6 +23,9 @@
|
|
|
#define ETHERNETMANAGER NETMANAGER->getEthernetManager()
|
|
|
#define WIFIMANAGER NETMANAGER->getWifiManager()
|
|
|
|
|
|
+#define DISCOVERY_PORT 8031
|
|
|
+#define DISCOVERY_TIMEOUT 10
|
|
|
+#define CONNECTION_TIMEOUT 120
|
|
|
|
|
|
void udpHandleMsg(byte* msg);
|
|
|
|
|
@@ -36,28 +42,28 @@ UdpClient* UdpClient::instance() {
|
|
|
return &singleton;
|
|
|
}
|
|
|
|
|
|
+static net::Conn* discover_conn;
|
|
|
static net::Conn* conn;
|
|
|
|
|
|
void UdpClient::sendMsg(const char* msg){
|
|
|
- instance()->internalSendMsg(msg);
|
|
|
+ instance()->internalSendMsg(msg, conn);
|
|
|
}
|
|
|
|
|
|
-void UdpClient::sendMsgWithCb(const char* msg){
|
|
|
- instance()->internalSendMsg(msg);
|
|
|
+void UdpClient::sendMsg(const char* msg, net::Conn* _conn){
|
|
|
+ instance()->internalSendMsg(msg, conn);
|
|
|
}
|
|
|
|
|
|
-void UdpClient::internalSendMsg(const char* msg){
|
|
|
+void UdpClient::internalSendMsg(const char* msg, net::Conn* _conn) {
|
|
|
if (busy_) {
|
|
|
LOGD("udp client is busy");
|
|
|
return;
|
|
|
}
|
|
|
busy_ = true;
|
|
|
- std::string msgStr = msg;
|
|
|
std::string endDelimiter = "#END#";
|
|
|
- std::string finalMsg = msg + endDelimiter;
|
|
|
- const char* sendMsg = finalMsg.c_str();
|
|
|
- if (conn){
|
|
|
- conn->Write((byte*)(sendMsg), strlen(sendMsg));
|
|
|
+ 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");
|
|
@@ -97,12 +103,13 @@ std::string getBoasrAddress() {
|
|
|
}
|
|
|
}
|
|
|
else if (WIFIMANAGER->isConnected()) {
|
|
|
- if (WIFIMANAGER->isAutoMode()) {
|
|
|
- WIFIMANAGER->getConfigureInfo(ip, mask, gateway, dns1, dns2);
|
|
|
- }
|
|
|
- else {
|
|
|
- WIFIMANAGER->getStaticConfigureInfo(ip, mask, gateway, dns1, dns2);
|
|
|
- }
|
|
|
+ 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];
|
|
@@ -122,14 +129,225 @@ std::string getBoasrAddress() {
|
|
|
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]) + ":8030";
|
|
|
+ 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;
|
|
|
+ }
|
|
|
|
|
|
-class UdpClientThread: public Thread {
|
|
|
public:
|
|
|
+
|
|
|
/**
|
|
|
* 线程创建成功后会调用该函数,可以在该函数中做一些初始化操作
|
|
|
* return true 继续线程
|
|
@@ -155,39 +373,18 @@ public:
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- // 设置一个默认地址
|
|
|
- std::string boasrAddress = "172.28.100.100:8030";
|
|
|
- if (ETHERNETMANAGER->isConnected() || WIFIMANAGER->isConnected()) {
|
|
|
- boasrAddress = getBoasrAddress();
|
|
|
- }
|
|
|
- LOGD("UDP广播地址 ===> %s", boasrAddress.c_str());
|
|
|
-
|
|
|
-
|
|
|
- conn = net::Dial("udp", boasrAddress);
|
|
|
- if (conn) {
|
|
|
- byte buf[2048] = {0};
|
|
|
-
|
|
|
- Json::Value reqJson;
|
|
|
- reqJson["IPaddress"] = ip;
|
|
|
- reqJson["mac-address"] = StoragePreferences::getString(STORE_MAC_ADDR, "0.0.0.0");
|
|
|
- reqJson["Gateway"] = gateway;
|
|
|
- reqJson["SubnetMask"] = mask;
|
|
|
- reqJson["sw-version"] = versionCode;
|
|
|
- reqJson["Hardware"] = "";
|
|
|
- reqJson["Id"] = StoragePreferences::getInt(STORE_DEVICE_ID, 0);
|
|
|
-
|
|
|
- Json::FastWriter writer;
|
|
|
- const std::string req = writer.write(reqJson);
|
|
|
- UdpClient::instance()->sendMsg(req.c_str());
|
|
|
-
|
|
|
- //关闭连接
|
|
|
- conn->Close();
|
|
|
- //释放内存
|
|
|
- delete conn;
|
|
|
- conn = NULL;
|
|
|
+ switch (current_state_) {
|
|
|
+ case STATE_DISCOVERING:
|
|
|
+ handleDiscoveryState();
|
|
|
+ break;
|
|
|
+ case STATE_CONNECTED:
|
|
|
+ handleConnectedState();
|
|
|
+ break;
|
|
|
+ case STATE_DISCONNECT:
|
|
|
+ return false;
|
|
|
+ break;
|
|
|
}
|
|
|
- //返回真,继续下次线程循环
|
|
|
- return false;
|
|
|
+ return true;
|
|
|
}
|
|
|
};
|
|
|
|
|
@@ -196,7 +393,9 @@ static UdpClientThread udp_thread;
|
|
|
void UdpClient::startUdp(){
|
|
|
LOGD("运行Udp线程");
|
|
|
//调用线程类的run函数启动线程, 参数为线程名,可以任意指定。
|
|
|
- udp_thread.run("udp thread");
|
|
|
+ if (!udp_thread.isRunning()) {
|
|
|
+ udp_thread.run("udp thread");
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void UdpClient::closeUdp() {
|
|
@@ -213,7 +412,7 @@ bool UdpClient::busy() {
|
|
|
}
|
|
|
|
|
|
bool UdpClient::connected() {
|
|
|
- return conn != NULL;
|
|
|
+ return conn != NULL || discover_conn != NULL;
|
|
|
}
|
|
|
|
|
|
|