数据流Stream去掉读写模版,改用普通读写函数,针对整数进行操作。

模版容易错误识别,并且导致可以直接写入字符串指针等隐含错误。
This commit is contained in:
nnhy 2015-10-10 14:20:37 +00:00
parent 8feaeaa5c3
commit d45e8b0886
14 changed files with 131 additions and 53 deletions

View File

@ -1,5 +1,6 @@
#include "W5500.h"
#include "Time.h"
#include "Task.h"
#define NET_DEBUG DEBUG
@ -303,7 +304,12 @@ bool W5500::Open()
//if(!TaskID) TaskID = Sys.AddTask(IRQTask, this, -1, -1, "W5500中断");
// 为解决芯片有时候无法接收数据的问题,需要守护任务辅助
if(!TaskID) TaskID = Sys.AddTask(IRQTask, this, 0, 1000, "W5500中断");
if(!TaskID)
{
TaskID = Sys.AddTask(IRQTask, this, 0, 1000, "W5500中断");
Task* task = Task::Get(TaskID);
task->MaxDeepth = 2; // 以太网允许重入,因为有时候在接收里面等待下一次接收
}
Opened = true;
@ -1339,7 +1345,7 @@ void UdpClient::RaiseReceive()
ByteArray bs2(6);
ms.Read(bs2);
ushort len = ms.Read<ushort>();
ushort len = ms.ReadUInt16();
len = __REV16(len);
// 数据长度不对可能是数据错位引起的,直接丢弃数据包
if(len > 1500)

View File

@ -32,18 +32,15 @@ void Message::SetData(const ByteArray& bs, uint offset)
void Message::SetError(byte errorCode, const char* msg)
{
/*byte* p = Data;
*p++ = errorCode;
while(msg) *p++ = (byte)*msg++;
Length = p - Data;*/
byte* p = (byte*)msg;
uint len = 0;
while(*p++) len++;
Error = true;
Stream ms(Data, MaxDataSize());
ms.Write(errorCode);
ms.Write(msg);
ms.Write((const byte*)msg, 0, len);
Length = ms.Position();
}

View File

@ -31,7 +31,7 @@ bool Modbus::Read(Stream& ms)
Length = ms.Remain() - 2;
ms.Read(&Data, 0, Length);
Crc = ms.Read<ushort>();
Crc = ms.ReadUInt16();
// 直接计算Crc16
Crc2 = Sys.Crc16(buf, ms.Position() - p - 2);

View File

@ -176,16 +176,16 @@ void Dhcp::PareOption(Stream& ms)
{
while(ms.Remain())
{
byte opt = ms.Read<byte>();
byte opt = ms.ReadByte();
if(opt == DHCP_OPT_End) break;
byte len = ms.Read<byte>();
byte len = ms.ReadByte();
// 有些家用路由器会发送错误的len大于4字节导致覆盖前后数据
switch(opt)
{
case DHCP_OPT_Mask: Host->Mask = ms.Read<int>(); len -= 4; break;
case DHCP_OPT_DNSServer: Host->DNSServer = ms.Read<int>(); len -= 4; break;
case DHCP_OPT_Router: Host->Gateway = ms.Read<int>(); len -= 4; break;
case DHCP_OPT_DHCPServer: Host->DHCPServer = ms.Read<int>(); len -= 4; break;
case DHCP_OPT_Mask: Host->Mask = ms.ReadUInt32(); len -= 4; break;
case DHCP_OPT_DNSServer: Host->DNSServer = ms.ReadUInt32(); len -= 4; break;
case DHCP_OPT_Router: Host->Gateway = ms.ReadUInt32(); len -= 4; break;
case DHCP_OPT_DHCPServer: Host->DHCPServer= ms.ReadUInt32(); len -= 4; break;
//default:
// debug_printf("Unkown DHCP Option=%d Length=%d\r\n", opt, len);
}

View File

@ -19,6 +19,7 @@ Stream::Stream(uint len)
_Position = 0;
Length = len;
_canWrite = true;
Little = true;
}
// 使用缓冲区初始化数据流。注意此时指针位于0而内容长度为缓冲区长度
@ -33,6 +34,7 @@ Stream::Stream(byte* buf, uint len)
_needFree = false;
_canWrite = true;
Length = len;
Little = true;
}
Stream::Stream(const byte* buf, uint len)
@ -45,6 +47,7 @@ Stream::Stream(const byte* buf, uint len)
_needFree = false;
_canWrite = false;
Length = len;
Little = true;
}
// 使用字节数组初始化数据流。注意此时指针位于0而内容长度为缓冲区长度
@ -56,6 +59,7 @@ Stream::Stream(ByteArray& bs)
_needFree = false;
_canWrite = true;
Length = bs.Length();
Little = true;
}
Stream::Stream(const ByteArray& bs)
@ -66,6 +70,7 @@ Stream::Stream(const ByteArray& bs)
_needFree = false;
_canWrite = false;
Length = bs.Length();
Little = true;
}
// 销毁数据流
@ -147,7 +152,7 @@ uint Stream::ReadEncodeInt()
byte temp = 0;
for(int i = 0, k = 0; i < 4; i++, k += 7)
{
temp = Read<byte>();
temp = ReadByte();
if(temp < 0x7F)
{
value |= (temp << k);
@ -350,3 +355,62 @@ bool Stream::WriteString(const String& str)
ByteArray bs(str);
return WriteArray(bs);
}
byte Stream::ReadByte()
{
byte* p = Current();
if(!Seek(1)) return 0;
return *p;
}
ushort Stream::ReadUInt16()
{
byte* p = ReadBytes(2);
ushort v = *(ushort*)p;
if(!Little) v = __REV16(v);
return v;
}
uint Stream::ReadUInt32()
{
byte* p = ReadBytes(4);
uint v = *(uint*)p;
if(!Little) v = __REV(v);
return v;
}
ulong Stream::ReadUInt64()
{
byte* p = ReadBytes(8);
ulong v = *(ulong*)p;
if(!Little) v = __REV(v >> 32) | ((ulong)__REV(v & 0xFFFFFFFF) << 32);
return v;
}
bool Stream::Write(byte value)
{
return Write((byte*)&value, 0, 1);
}
bool Stream::Write(ushort value)
{
if(!Little) value = __REV16(value);
return Write((byte*)&value, 0, 2);
}
bool Stream::Write(uint value)
{
if(!Little) value = __REV(value);
return Write((byte*)&value, 0, 4);
}
bool Stream::Write(ulong value)
{
if(!Little) value = __REV(value >> 32) | ((ulong)__REV(value & 0xFFFFFFFF) << 32);
return Write((byte*)&value, 0, 8);
}

View File

@ -11,14 +11,14 @@ class Stream
private:
byte* _Buffer; // 数据缓冲区。扩容后会重新分配缓冲区
uint _Capacity; // 缓冲区容量
bool _needFree; // 是否自动释放
bool _canWrite; // 是否可写
// 又是头疼的对齐问题
ushort _Reserved;
uint _Position; // 游标位置
byte _Arr[64]; // 内部缓冲区。较小内存需要时,直接使用栈分配,提高性能。
bool _needFree; // 是否自动释放
bool _canWrite; // 是否可写
public:
bool Little; // 默认小字节序。仅影响数据读写操作
uint Length; // 数据长度
// 分配指定大小的数据流
@ -78,6 +78,16 @@ public:
// 把字符串作为变长数据写入到数据流。以压缩整数开头表示长度
bool WriteString(const String& str);
byte ReadByte();
ushort ReadUInt16();
uint ReadUInt32();
ulong ReadUInt64();
bool Write(byte value);
bool Write(ushort value);
bool Write(uint value);
bool Write(ulong value);
// 取回指定结构体指针,并移动游标位置
template<typename T>
T* Retrieve(bool move = true)
@ -92,7 +102,7 @@ public:
return pt;
}
// 常用读写整数方法
/*// 常用读写整数方法
template<typename T>
T Read()
{
@ -112,6 +122,7 @@ public:
template<typename T>
bool Write(T value)
{
if(!_canWrite) return false;
if(!CheckRemain(sizeof(T))) return false;
byte* p = Current();
@ -127,7 +138,7 @@ public:
if(_Position > Length) Length = _Position;
return true;
}
}*/
// 读取指定长度的数据并返回首字节指针,移动数据流位置
byte* ReadBytes(int count = -1);

View File

@ -33,13 +33,13 @@ void Device::Write(Stream& ms) const
void Device::Read(Stream& ms)
{
Address = ms.Read<byte>();
Kind = ms.Read<ushort>();
Address = ms.ReadByte();
Kind = ms.ReadUInt16();
//ms.ReadArray(HardID);
HardID = ms.ReadArray();
LastTime= ms.Read<ulong>();
DataSize = ms.Read<byte>();
ConfigSize = ms.Read<byte>();
LastTime= ms.ReadUInt64();
DataSize = ms.ReadByte();
ConfigSize = ms.ReadByte();
Name = ms.ReadString();
}

View File

@ -14,15 +14,15 @@ bool DiscoverMessage::Read(Stream& ms)
{
if(!Reply)
{
Type = ms.Read<ushort>();
Type = ms.ReadUInt16();
HardID = ms.ReadArray();
Version = ms.Read<ushort>();
Switchs = ms.Read<byte>();
Analogs = ms.Read<byte>();
Version = ms.ReadUInt16();
Switchs = ms.ReadByte();
Analogs = ms.ReadByte();
}
else
{
Address = ms.Read<byte>();
Address = ms.ReadByte();
Pass = ms.ReadArray();
}

View File

@ -18,19 +18,19 @@ bool JoinMessage::Read(Stream& ms)
{
if(!Reply)
{
Version = ms.Read<byte>();
Kind = ms.Read<ushort>();
TranID = ms.Read<uint>();
Version = ms.ReadByte();
Kind = ms.ReadUInt16();
TranID = ms.ReadUInt32();
HardID = ms.ReadArray();
}
else
{
Server = ms.Read<byte>();
Channel = ms.Read<byte>();
Speed = ms.Read<byte>();
Address = ms.Read<byte>();
Server = ms.ReadByte();
Channel = ms.ReadByte();
Speed = ms.ReadByte();
Address = ms.ReadByte();
Password= ms.ReadArray();
TranID = ms.Read<uint>();
TranID = ms.ReadUInt32();
HardID = ms.ReadArray();
}

View File

@ -70,7 +70,7 @@ bool TinyMessage::Read(Stream& ms)
if(Length > 0) ms.Read(Data, 0, Length);
// 读取真正的校验码
Checksum = ms.Read<ushort>();
Checksum = ms.ReadUInt16();
// 计算Crc之前需要清零TTL和Retry
byte fs = p[3];

View File

@ -33,15 +33,15 @@ HelloMessage::HelloMessage(HelloMessage& msg) : Ciphers(1), Key(0)
// 从数据流中读取消息
bool HelloMessage::Read(Stream& ms)
{
Version = ms.Read<ushort>();
Version = ms.ReadUInt16();
Type = ms.ReadString();
Name = ms.ReadString();
LocalTime = ms.Read<ulong>();
LocalTime = ms.ReadUInt64();
EndPoint.Address = ms.ReadBytes(4);
EndPoint.Port = ms.Read<ushort>();
EndPoint.Port = ms.ReadUInt16();
if(!Reply)
{
@ -49,7 +49,7 @@ bool HelloMessage::Read(Stream& ms)
}
else
{
Ciphers[0] = ms.Read<byte>();
Ciphers[0] = ms.ReadByte();
// 读取数组前先设置为0避免实际长度小于数组长度
Key.SetLength(0);
Key = ms.ReadArray();

View File

@ -16,7 +16,7 @@ bool LoginMessage::Read(Stream& ms)
ms.ReadArray(Salt);
Local.Address = ms.ReadBytes(4);
Local.Port = ms.Read<ushort>();
Local.Port = ms.ReadUInt16();
return false;
}

View File

@ -175,7 +175,7 @@ bool TokenClient::OnHello(TokenMessage& msg)
Status = 0;
Token = 0;
Stream ms(msg.Data, msg.Length);
debug_printf("握手失败,错误码=0x%02X ", ms.Read<byte>());
debug_printf("握手失败,错误码=0x%02X ", ms.ReadByte());
ms.ReadString().Show(true);
}
else
@ -241,7 +241,7 @@ bool TokenClient::OnLogin(TokenMessage& msg)
// 登录失败,清空令牌
Token = 0;
byte result = ms.Read<byte>();
byte result = ms.ReadByte();
//if(result == 0xFF) Status = 0;
// 任何错误,重新握手
Status = 0;
@ -256,10 +256,10 @@ bool TokenClient::OnLogin(TokenMessage& msg)
if(IsOldOrder)
{
byte stat=ms.Read<byte>();//旧指令,读走状态码
byte stat=ms.ReadByte();//旧指令,读走状态码
}
// 得到令牌
Token = ms.Read<int>();
Token = ms.ReadUInt32();
debug_printf("令牌0x%08X ", Token);
// 这里可能有通信密码
if(ms.Remain() > 0)

View File

@ -26,11 +26,11 @@ bool TokenMessage::Read(Stream& ms)
assert_ptr(this);
if(ms.Remain() < MinSize) return false;
byte temp = ms.Read<byte>();
byte temp = ms.ReadByte();
Code = temp & 0x3f;
Reply = temp >> 7;
Error = (temp >> 6) & 0x01;
Length = ms.Read<byte>();
Length = ms.ReadByte();
// 占位符拷贝到实际数据
/*Code = _Code;