完善物联协议,登录请求Json数据包成功发给服务端并收到
This commit is contained in:
parent
1abdedef5a
commit
0bd0d82c8c
|
@ -26,12 +26,7 @@ LinkClient::LinkClient()
|
|||
Delay = 0;
|
||||
MaxNotActive = 0;
|
||||
|
||||
NextReport = -1;
|
||||
ReportLength = 0;
|
||||
|
||||
_Expect = nullptr;
|
||||
|
||||
assert(!Current, "只能有一个令牌客户端实例");
|
||||
assert(!Current, "只能有一个物联客户端实例");
|
||||
Current = this;
|
||||
}
|
||||
|
||||
|
@ -42,7 +37,7 @@ void LinkClient::Open()
|
|||
TS("LinkClient::Open");
|
||||
|
||||
// 令牌客户端定时任务
|
||||
_task = Sys.AddTask(&LinkClient::LoopTask, this, 0, 1000, "令牌客户");
|
||||
_task = Sys.AddTask(&LinkClient::LoopTask, this, 0, 1000, "物联客户");
|
||||
|
||||
// 启动时记为最后一次活跃接收
|
||||
LastActive = Sys.Ms();
|
||||
|
@ -55,24 +50,89 @@ void LinkClient::Close()
|
|||
if (!Opened) return;
|
||||
|
||||
Sys.RemoveTask(_task);
|
||||
//Sys.RemoveTask(_taskBroadcast);
|
||||
|
||||
Opened = false;
|
||||
}
|
||||
|
||||
bool LinkClient::Send(LinkMessage& msg) {
|
||||
return false;
|
||||
void LinkClient::CheckNet()
|
||||
{
|
||||
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];
|
||||
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 += "\",\"args\":}";
|
||||
str += "\",\"args\":{";
|
||||
str += args;
|
||||
str += "\"}";
|
||||
|
||||
|
@ -92,3 +152,122 @@ bool LinkClient::Invoke(String& action, String& args) {
|
|||
// 发送
|
||||
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 MaxNotActive; // 最大不活跃时间ms,超过该时间时重启系统。默认0
|
||||
|
||||
Socket* Socket;
|
||||
NetUri Server;
|
||||
String User;
|
||||
String Pass;
|
||||
|
||||
Socket* Master; // 主链接。服务器长连接
|
||||
DataStore Store; // 数据存储区
|
||||
Dictionary<cstring, IDelegate*> Routes; // 路由集合
|
||||
|
||||
|
@ -31,84 +35,32 @@ public:
|
|||
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);
|
||||
void OnReceive(String& data);
|
||||
void LocalSend(int start, const Buffer& bs);
|
||||
|
||||
// 收到功能消息时触发
|
||||
//MessageHandler Received;
|
||||
void* Param;
|
||||
|
||||
// 常用系统级消息
|
||||
// 握手广播
|
||||
void SayHello(bool broadcast);
|
||||
|
||||
// 注册
|
||||
void Register();
|
||||
|
||||
// 登录
|
||||
void Login();
|
||||
// 重置并上报
|
||||
void Reset(const String& reason);
|
||||
void Reboot(const String& reason);
|
||||
|
||||
// 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;
|
||||
|
||||
private:
|
||||
bool Send(LinkMessage& msg);
|
||||
|
||||
// 跳转
|
||||
/*bool OnRedirect(IDictionary);
|
||||
bool Send(const 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);*/
|
||||
bool OnPing(LinkMessage& msg);
|
||||
bool OnLogin(LinkMessage& msg);
|
||||
|
||||
private:
|
||||
uint _task;
|
||||
void* _Expect; // 等待内容
|
||||
|
||||
int NextReport = -1; // 下次上报偏移,-1不动
|
||||
byte ReportLength; // 下次上报数据长度
|
||||
|
||||
void LoopTask();
|
||||
bool CheckReport();
|
||||
void CheckNet();
|
||||
};
|
||||
|
||||
|
|
|
@ -13,5 +13,11 @@
|
|||
void LinkMessage::Init() {
|
||||
*(byte*)Reply = 0;
|
||||
Seq = 0;
|
||||
Code = 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 String GetString() const { return String((cstring)&this[1], Length); }
|
||||
|
||||
void Init();
|
||||
|
||||
void Show(bool newline = false) const;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
|
|
@ -107,6 +107,7 @@
|
|||
<ClCompile Include="..\Kernel\Time.cpp" />
|
||||
<ClCompile Include="..\Kernel\WaitHandle.cpp" />
|
||||
<ClCompile Include="..\Link\LinkClient.cpp" />
|
||||
<ClCompile Include="..\Link\LinkMessage.cpp" />
|
||||
<ClCompile Include="..\Message\BinaryPair.cpp" />
|
||||
<ClCompile Include="..\Message\Controller.cpp" />
|
||||
<ClCompile Include="..\Message\DataStore.cpp" />
|
||||
|
|
|
@ -587,5 +587,8 @@
|
|||
<ClCompile Include="..\Link\LinkClient.cpp">
|
||||
<Filter>Link</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Link\LinkMessage.cpp">
|
||||
<Filter>Link</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
Reference in New Issue