完善物联协议,登录请求Json数据包成功发给服务端并收到
This commit is contained in:
parent
1abdedef5a
commit
0bd0d82c8c
|
@ -26,12 +26,7 @@ LinkClient::LinkClient()
|
||||||
Delay = 0;
|
Delay = 0;
|
||||||
MaxNotActive = 0;
|
MaxNotActive = 0;
|
||||||
|
|
||||||
NextReport = -1;
|
assert(!Current, "只能有一个物联客户端实例");
|
||||||
ReportLength = 0;
|
|
||||||
|
|
||||||
_Expect = nullptr;
|
|
||||||
|
|
||||||
assert(!Current, "只能有一个令牌客户端实例");
|
|
||||||
Current = this;
|
Current = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +37,7 @@ void LinkClient::Open()
|
||||||
TS("LinkClient::Open");
|
TS("LinkClient::Open");
|
||||||
|
|
||||||
// 令牌客户端定时任务
|
// 令牌客户端定时任务
|
||||||
_task = Sys.AddTask(&LinkClient::LoopTask, this, 0, 1000, "令牌客户");
|
_task = Sys.AddTask(&LinkClient::LoopTask, this, 0, 1000, "物联客户");
|
||||||
|
|
||||||
// 启动时记为最后一次活跃接收
|
// 启动时记为最后一次活跃接收
|
||||||
LastActive = Sys.Ms();
|
LastActive = Sys.Ms();
|
||||||
|
@ -55,24 +50,89 @@ void LinkClient::Close()
|
||||||
if (!Opened) return;
|
if (!Opened) return;
|
||||||
|
|
||||||
Sys.RemoveTask(_task);
|
Sys.RemoveTask(_task);
|
||||||
//Sys.RemoveTask(_taskBroadcast);
|
|
||||||
|
|
||||||
Opened = false;
|
Opened = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LinkClient::Send(LinkMessage& msg) {
|
void LinkClient::CheckNet()
|
||||||
return false;
|
{
|
||||||
|
auto mst = Master;
|
||||||
|
|
||||||
|
// 检测主链接
|
||||||
|
if (!mst)
|
||||||
|
{
|
||||||
|
auto uri = Server;
|
||||||
|
// 创建连接服务器的Socket
|
||||||
|
auto socket = Socket::CreateRemote(uri);
|
||||||
|
if (!socket) return;
|
||||||
|
|
||||||
|
Master = socket;
|
||||||
|
|
||||||
|
debug_printf("LinkClient::CheckNet %s 成功创建主连接\r\n", socket->Host->Name);
|
||||||
|
|
||||||
|
// 已连接时,减慢网络检查速度
|
||||||
|
Sys.SetTaskPeriod(_task, 5000);
|
||||||
|
}
|
||||||
|
// 检测主链接是否已经断开
|
||||||
|
else if (!mst->Host->Linked)
|
||||||
|
{
|
||||||
|
debug_printf("LinkClient::CheckNet %s断开,切换主连接\r\n", mst->Host->Name);
|
||||||
|
|
||||||
|
delete mst;
|
||||||
|
Master = nullptr;
|
||||||
|
|
||||||
|
Status = 0;
|
||||||
|
|
||||||
|
// 未连接时,加快网络检查速度
|
||||||
|
Sys.SetTaskPeriod(_task, 1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LinkClient::Invoke(String& action, String& args) {
|
// 定时任务
|
||||||
|
void LinkClient::LoopTask()
|
||||||
|
{
|
||||||
|
TS("LinkClient::LoopTask");
|
||||||
|
|
||||||
|
// 最大不活跃时间ms,超过该时间时重启系统
|
||||||
|
// WiFi触摸开关建议5~10分钟,网关建议5分钟
|
||||||
|
// MaxNotActive 为零便不考虑重启
|
||||||
|
if (MaxNotActive != 0 && LastActive + MaxNotActive < Sys.Ms()) Sys.Reboot();
|
||||||
|
|
||||||
|
CheckNet();
|
||||||
|
if (!Master) return;
|
||||||
|
|
||||||
|
// 状态。0准备、1握手完成、2登录后
|
||||||
|
switch (Status)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
Login();
|
||||||
|
|
||||||
|
// 登录成功后,心跳一次,把数据同步上去
|
||||||
|
Sys.Sleep(1000);
|
||||||
|
if (Status >= 2) Ping();
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
Ping();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LinkClient::Send(const LinkMessage& msg) {
|
||||||
|
return Master->Send(msg.GetString());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LinkClient::Invoke(const String& action, const String& args) {
|
||||||
// 消息缓冲区,跳过头部
|
// 消息缓冲区,跳过头部
|
||||||
char cs[512];
|
char cs[512];
|
||||||
String str(&cs[sizeof(LinkMessage)], sizeof(cs) - sizeof(LinkMessage));
|
String str(&cs[sizeof(LinkMessage)], sizeof(cs) - sizeof(LinkMessage), false);
|
||||||
|
str.SetLength(0);
|
||||||
|
|
||||||
// 构造内容
|
// 构造内容
|
||||||
str += "{\"action\":\"";
|
str += "{\"action\":\"";
|
||||||
str += action;
|
str += action;
|
||||||
str += "\",\"args\":}";
|
str += "\",\"args\":{";
|
||||||
str += args;
|
str += args;
|
||||||
str += "\"}";
|
str += "\"}";
|
||||||
|
|
||||||
|
@ -92,3 +152,122 @@ bool LinkClient::Invoke(String& action, String& args) {
|
||||||
// 发送
|
// 发送
|
||||||
return Send(msg);
|
return Send(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 登录
|
||||||
|
void LinkClient::Login()
|
||||||
|
{
|
||||||
|
TS("LinkClient::Login");
|
||||||
|
|
||||||
|
Json json;
|
||||||
|
String args;
|
||||||
|
json.SetOut(args);
|
||||||
|
|
||||||
|
json.Add("User", User);
|
||||||
|
|
||||||
|
// 原始密码对盐值进行加密,得到登录密码
|
||||||
|
auto now = DateTime::Now().TotalMs();
|
||||||
|
auto arr = Buffer(&now, 8);
|
||||||
|
ByteArray bs;
|
||||||
|
bs = arr;
|
||||||
|
RC4::Encrypt(arr, Pass);
|
||||||
|
// 散列明文和密码连接在一起
|
||||||
|
auto pass = bs.ToHex();
|
||||||
|
pass += arr.ToHex();
|
||||||
|
|
||||||
|
json.Add("Password", pass);
|
||||||
|
|
||||||
|
Invoke("Login", args);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LinkClient::OnLogin(LinkMessage& msg)
|
||||||
|
{
|
||||||
|
if (!msg.Reply) return false;
|
||||||
|
|
||||||
|
TS("LinkClient::OnLogin");
|
||||||
|
|
||||||
|
msg.Show(true);
|
||||||
|
|
||||||
|
auto str = msg.GetString();
|
||||||
|
//Json json = str;
|
||||||
|
|
||||||
|
if (msg.Error)
|
||||||
|
{
|
||||||
|
Status = 0;
|
||||||
|
debug_printf("登录失败!\r\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Status = 2;
|
||||||
|
debug_printf("登录成功!\r\n");
|
||||||
|
|
||||||
|
// 登录成功后加大心跳间隔
|
||||||
|
Sys.SetTaskPeriod(_task, 60000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 心跳,用于保持与对方的活动状态
|
||||||
|
void LinkClient::Ping()
|
||||||
|
{
|
||||||
|
TS("LinkClient::Ping");
|
||||||
|
|
||||||
|
if (LastActive > 0 && LastActive + 300000 < Sys.Ms())
|
||||||
|
{
|
||||||
|
// 30秒无法联系,服务端可能已经掉线,重启Hello任务
|
||||||
|
debug_printf("300秒无法联系,服务端可能已经掉线,重新开始握手\r\n");
|
||||||
|
|
||||||
|
delete Master;
|
||||||
|
Master = nullptr;
|
||||||
|
|
||||||
|
Status = 0;
|
||||||
|
|
||||||
|
Sys.SetTaskPeriod(_task, 5000);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 30秒内发过数据,不再发送心跳
|
||||||
|
if (LastSend > 0 && LastSend + 60000 > Sys.Ms()) return;
|
||||||
|
|
||||||
|
Json json;
|
||||||
|
String args;
|
||||||
|
json.SetOut(args);
|
||||||
|
|
||||||
|
//json.Add("Data", Store.Data.ToHex());
|
||||||
|
|
||||||
|
// 原始密码对盐值进行加密,得到登录密码
|
||||||
|
auto ms = (int)Sys.Ms();
|
||||||
|
json.Add("Time", ms);
|
||||||
|
|
||||||
|
Invoke("Ping", args);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LinkClient::OnPing(LinkMessage& msg)
|
||||||
|
{
|
||||||
|
TS("LinkClient::OnPing");
|
||||||
|
|
||||||
|
if (!msg.Reply) return false;
|
||||||
|
|
||||||
|
msg.Show(true);
|
||||||
|
if (msg.Error) return false;
|
||||||
|
|
||||||
|
auto str = msg.GetString();
|
||||||
|
Json json = str;
|
||||||
|
|
||||||
|
int ms = json["Time"].AsInt();
|
||||||
|
int cost = (int)(Sys.Ms() - ms);
|
||||||
|
|
||||||
|
if (Delay)
|
||||||
|
Delay = (Delay + cost) / 2;
|
||||||
|
else
|
||||||
|
Delay = cost;
|
||||||
|
|
||||||
|
debug_printf("心跳延迟 %dms / %dms \r\n", cost, Delay);
|
||||||
|
|
||||||
|
// 同步本地时间
|
||||||
|
int serverTime = json["ServerTime"].AsInt();
|
||||||
|
if (serverTime > 1000) ((TTime&)Time).SetTime(serverTime);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -21,7 +21,11 @@ public:
|
||||||
int Delay; // 心跳延迟。一条心跳指令从发出到收到所花费的时间
|
int Delay; // 心跳延迟。一条心跳指令从发出到收到所花费的时间
|
||||||
int MaxNotActive; // 最大不活跃时间ms,超过该时间时重启系统。默认0
|
int MaxNotActive; // 最大不活跃时间ms,超过该时间时重启系统。默认0
|
||||||
|
|
||||||
Socket* Socket;
|
NetUri Server;
|
||||||
|
String User;
|
||||||
|
String Pass;
|
||||||
|
|
||||||
|
Socket* Master; // 主链接。服务器长连接
|
||||||
DataStore Store; // 数据存储区
|
DataStore Store; // 数据存储区
|
||||||
Dictionary<cstring, IDelegate*> Routes; // 路由集合
|
Dictionary<cstring, IDelegate*> Routes; // 路由集合
|
||||||
|
|
||||||
|
@ -31,84 +35,32 @@ public:
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
// 发送消息
|
// 发送消息
|
||||||
bool Invoke(String& action, String& args);
|
bool Invoke(const String& action, const String& args);
|
||||||
bool Reply(String& action, int code, String& result, int seq);
|
bool Reply(String& action, int code, String& result, int seq);
|
||||||
void OnReceive(String& data);
|
void OnReceive(String& data);
|
||||||
void LocalSend(int start, const Buffer& bs);
|
|
||||||
|
|
||||||
// 收到功能消息时触发
|
// 收到功能消息时触发
|
||||||
//MessageHandler Received;
|
//MessageHandler Received;
|
||||||
void* Param;
|
void* Param;
|
||||||
|
|
||||||
// 常用系统级消息
|
|
||||||
// 握手广播
|
|
||||||
void SayHello(bool broadcast);
|
|
||||||
|
|
||||||
// 注册
|
|
||||||
void Register();
|
|
||||||
|
|
||||||
// 登录
|
// 登录
|
||||||
void Login();
|
void Login();
|
||||||
// 重置并上报
|
|
||||||
void Reset(const String& reason);
|
|
||||||
void Reboot(const String& reason);
|
|
||||||
|
|
||||||
// Ping指令用于保持与对方的活动状态
|
// 心跳,用于保持与对方的活动状态
|
||||||
void Ping();
|
void Ping();
|
||||||
|
|
||||||
/*void Read(int start, int size);
|
|
||||||
void Write(int start, const Buffer& bs);
|
|
||||||
void Write(int start, byte dat);
|
|
||||||
|
|
||||||
// 异步上传并等待响应,返回实际上传字节数
|
|
||||||
int WriteAsync(int start, const Buffer& bs, int msTimeout);
|
|
||||||
|
|
||||||
// 必须满足 start > 0 才可以。
|
|
||||||
void ReportAsync(int start, uint length = 1);
|
|
||||||
|
|
||||||
// 远程调用
|
|
||||||
void Invoke(const String& action, const Buffer& bs);
|
|
||||||
|
|
||||||
// 远程调用委托。传入参数名值对以及结果缓冲区引用,业务失败时返回false并把错误信息放在结果缓冲区
|
|
||||||
typedef bool(*InvokeHandler)(void* param, const Pair& args, Stream& result);
|
|
||||||
// 注册远程调用处理器
|
|
||||||
void Register(cstring action, InvokeHandler handler, void* param = nullptr);
|
|
||||||
// 模版支持成员函数
|
|
||||||
template<typename T>
|
|
||||||
void Register(cstring action, bool(T::*func)(const Pair&, Stream&), T* target)
|
|
||||||
{
|
|
||||||
Register(action, *(InvokeHandler*)&func, target);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
static LinkClient* Current;
|
static LinkClient* Current;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool Send(LinkMessage& msg);
|
bool Send(const LinkMessage& msg);
|
||||||
|
|
||||||
// 跳转
|
bool OnPing(LinkMessage& msg);
|
||||||
/*bool OnRedirect(IDictionary);
|
bool OnLogin(LinkMessage& msg);
|
||||||
|
|
||||||
bool OnLogin(TokenMessage& msg, TokenController* ctrl);
|
|
||||||
|
|
||||||
bool OnPing(TokenMessage& msg, TokenController* ctrl);
|
|
||||||
|
|
||||||
bool ChangeIPEndPoint(const NetUri& uri);
|
|
||||||
|
|
||||||
void OnRead(const TokenMessage& msg, TokenController* ctrl);
|
|
||||||
void OnWrite(const TokenMessage& msg, TokenController* ctrl);
|
|
||||||
|
|
||||||
void OnInvoke(const TokenMessage& msg, TokenController* ctrl);
|
|
||||||
bool OnInvoke(const String& action, const Pair& args, Stream& result);*/
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint _task;
|
uint _task;
|
||||||
void* _Expect; // 等待内容
|
|
||||||
|
|
||||||
int NextReport = -1; // 下次上报偏移,-1不动
|
|
||||||
byte ReportLength; // 下次上报数据长度
|
|
||||||
|
|
||||||
void LoopTask();
|
void LoopTask();
|
||||||
bool CheckReport();
|
|
||||||
void CheckNet();
|
void CheckNet();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,5 +13,11 @@
|
||||||
void LinkMessage::Init() {
|
void LinkMessage::Init() {
|
||||||
*(byte*)Reply = 0;
|
*(byte*)Reply = 0;
|
||||||
Seq = 0;
|
Seq = 0;
|
||||||
|
Code = 0;
|
||||||
Length = 0;
|
Length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LinkMessage::Show(bool newline) const {
|
||||||
|
String str((cstring)&this[1], Length);
|
||||||
|
str.Show(newline);
|
||||||
|
}
|
||||||
|
|
|
@ -18,9 +18,12 @@ public:
|
||||||
|
|
||||||
// 数据指针
|
// 数据指针
|
||||||
const void* Data() const { return (const void*)&this[1]; }
|
const void* Data() const { return (const void*)&this[1]; }
|
||||||
|
const String GetString() const { return String((cstring)&this[1], Length); }
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
|
void Show(bool newline = false) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -107,6 +107,7 @@
|
||||||
<ClCompile Include="..\Kernel\Time.cpp" />
|
<ClCompile Include="..\Kernel\Time.cpp" />
|
||||||
<ClCompile Include="..\Kernel\WaitHandle.cpp" />
|
<ClCompile Include="..\Kernel\WaitHandle.cpp" />
|
||||||
<ClCompile Include="..\Link\LinkClient.cpp" />
|
<ClCompile Include="..\Link\LinkClient.cpp" />
|
||||||
|
<ClCompile Include="..\Link\LinkMessage.cpp" />
|
||||||
<ClCompile Include="..\Message\BinaryPair.cpp" />
|
<ClCompile Include="..\Message\BinaryPair.cpp" />
|
||||||
<ClCompile Include="..\Message\Controller.cpp" />
|
<ClCompile Include="..\Message\Controller.cpp" />
|
||||||
<ClCompile Include="..\Message\DataStore.cpp" />
|
<ClCompile Include="..\Message\DataStore.cpp" />
|
||||||
|
|
|
@ -587,5 +587,8 @@
|
||||||
<ClCompile Include="..\Link\LinkClient.cpp">
|
<ClCompile Include="..\Link\LinkClient.cpp">
|
||||||
<Filter>Link</Filter>
|
<Filter>Link</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\Link\LinkMessage.cpp">
|
||||||
|
<Filter>Link</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Loading…
Reference in New Issue