你怎么解释这句话?
校验
这是从标头到校验和的低8位加零的值。
使用此协议说明:
协定
包括头(1字节)+数据长度(1字节)+ 命令数据(13字节)+校验和(1字节)+连接ID(1 字节)。
(我真的复制了这个协议描述,所以我不知道为什么有1 bytes
(复数形式)。但我可以告诉你它只有一个字节)
以下是此协议的一些示例TCP数据包:
HE:DL:------------Command Data -------------:CS:ID
02:0d:be:ef:03:06:00:19:d3:02:00:00:60:00:00:ed:01
02:0d:be:ef:03:06:00:cd:d2:02:00:00:20:00:00:7a:01
02:0d:be:ef:03:06:00:10:f6:02:00:ba:30:00:00:49:01
02:0d:be:ef:03:06:00:c8:d8:02:00:20:30:00:00:49:01
// Requested Packets
02:0d:be:ef:03:06:00:13:d3:01:00:02:30:01:00:21:01
02:0d:be:ef:03:06:00:c2:ff:02:00:90:10:00:00:d8:01
其中
HE
是标题(固定为0x02
)DL
是DataLength(始终为0x0d
,因为数据包的长度都相同)CS
是CheckSum(这是我的问题)ID
是连接ID(在我的测试中似乎总是01)我无法弄清楚如何计算校验和。我希望我提供足够的信息。
提前致谢。
答案 0 :(得分:3)
我认为说明中只有一个错误。看起来它们正在汇总标头和校验和之间的所有字节。校验和只是一个清除低8位的数字。因此,对于第一个示例,标头和校验和之间的所有字节总和为0x0313。或
0x0313 0000 0011 0001 0011
0x00ED 0000 0000 1110 1101
当它排成一行时,你可以清楚地看到你将零下8位归零并返回:
0x0400 0000 0100 0000 0000
您没有指定语言,但您也可以通过执行(0 XOR calculatedSum)+ 1快速计算自己的校验和。
答案 1 :(得分:2)
您
无论如何,这个C代码计算了所有4个例子的正确总和:
uint8_t silly_chksum(const uint8_t *data, size_t len)
{
size_t i;
unsigned int chk = -1;
for(i = 0; i < len ;i++)
{
chk += data[i];
}
return ~(chk & 0xff);
}
答案 2 :(得分:2)
为了好玩,我把它作为练习使用Boost Spirit(c ++)编写一个简单的二进制解析器。我包括了问题格式和校验和验证的转换。
我让解析器识别实际数据长度和任意选择STL容器的数据包数据。输出如下:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
namespace qi=boost::spirit::qi;
namespace karma=boost::spirit::karma;
namespace phx=boost::phoenix;
typedef unsigned char uchar;
static const auto inbyte = qi::uint_parser<unsigned char, 16, 2, 2>();
static const auto outbyte = karma::right_align(2,'0') [ karma::hex ];
// for some reason the alignment doesn't 'take' with the above, so HACK:
#define outbyte karma::right_align(2,'0') [ karma::hex ]
struct packet_t
{
enum { HEADER = 0x02 };
uchar checksum, id;
typedef std::string data_t;
/// the following work without modification:
// typedef std::vector<uchar> data_t;
// typedef std::list<int> data_t;
data_t data;
uchar do_checksum() const
{
return (uchar) -std::accumulate(data.begin(), data.end(),
HEADER + data.size());
}
bool is_valid() const
{ return checksum == do_checksum(); }
};
BOOST_FUSION_ADAPT_STRUCT(packet_t,
(packet_t::data_t, data) (uchar, checksum) (uchar, id));
int main()
{
static const std::string input =
"02:0d:be:ef:03:06:00:19:d3:02:00:00:60:00:00:ed:01\n"
"02:0d:be:ef:03:06:00:cd:d2:02:00:00:20:00:00:7a:01\n"
"02:0d:be:ef:03:06:00:10:f6:02:00:ba:30:00:00:49:01\n"
"02:0d:be:ef:03:06:00:c8:d8:02:00:20:30:00:00:49:01\n"
"02:08:c8:d8:02:00:20:30:00:00:49:01\n"; // failure test case
// convert hex to bytes
std::vector<std::vector<char> > rawpackets;
if (!qi::parse(input.begin(), input.end(), (inbyte % ':') % qi::eol, rawpackets))
{ std::cerr << "bailing" << std::endl; return 255; }
// std::cout << karma::format(karma::eps << outbyte % ':' % karma::eol, rawpackets) << std::endl;
// analyze & checksum packets
for (auto raw: rawpackets)
{
std::cout << karma::format(karma::eps << outbyte % ':', raw);
using namespace qi;
rule<decltype(raw.begin()), packet_t(), locals<uchar> > parser;
parser %= byte_(packet_t::HEADER)
> omit[ byte_ [ _a = _1 ] ] // datalen
> repeat(_a)[byte_] // data
> byte_ // checksum
> byte_; // id
packet_t packet;
if (!parse(raw.begin(), raw.end(), parser, packet))
{ std::cerr << " bailing" << std::endl; return 255; }
std::cout << " do_checksum():\t" << karma::format(outbyte, packet.do_checksum());
std::cout << " is_valid():\t" << std::boolalpha << packet.is_valid() << std::endl;
}
return 0;
}
输出
02:0d:be:ef:03:06:00:19:d3:02:00:00:60:00:00:ed:01 do_checksum(): ed is_valid(): true
02:0d:be:ef:03:06:00:cd:d2:02:00:00:20:00:00:7a:01 do_checksum(): 7a is_valid(): true
02:0d:be:ef:03:06:00:10:f6:02:00:ba:30:00:00:49:01 do_checksum(): 49 is_valid(): true
02:0d:be:ef:03:06:00:c8:d8:02:00:20:30:00:00:49:01 do_checksum(): 49 is_valid(): true
02:08:c8:d8:02:00:20:30:00:00:49:01 do_checksum(): 04 is_valid(): false
答案 3 :(得分:1)
如果在Header,DataLength,CommandData和CheckSum中添加所有十六进制数字,则会生成1024。
例如,这是第二个例子的总和(我跳过了0x00):
0x02+0x0d+0xbe+0xef+0x03+0x06+0xcd+0xd2+0x02+0x20+0x7a = 1024
截图(总和只是我写的一个javascript函数,用于自动对十六进制值求和):
修改强> 它不一定总和为1024,相反,如果它是有效的,它将总和为8个低位为0的数字,例如1024(100 <00> 00000000 ),768(11 <00> 00000000 )和1280(101 <00> 00000000 )。