Tcp 你如何解释这个短语?
你如何解释这个短语 校验和Tcp 你如何解释这个短语?,tcp,binary,protocols,checksum,Tcp,Binary,Protocols,Checksum,你如何解释这个短语 校验和 这是在从报头到校验和的低8位相加时使零的值 根据本协议说明: 协议 由标头(1字节)+数据长度(1字节)组成+ 命令数据(13字节)+校验和(1字节)+连接ID(1字节 字节) (我从字面上复制了这个协议描述,所以我不知道为什么会有1个字节(复数)。但我可以告诉你它只有一个字节) 以下是此协议的一些TCP数据包示例: HE:DL:------------Command Data -------------:CS:ID 02:0d:be:ef:03:06:00:19:d
这是在从报头到校验和的低8位相加时使零的值 根据本协议说明: 协议
由标头(1字节)+数据长度(1字节)组成+ 命令数据(13字节)+校验和(1字节)+连接ID(1字节 字节) (我从字面上复制了这个协议描述,所以我不知道为什么会有
1个字节
(复数)。但我可以告诉你它只有一个字节)
以下是此协议的一些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
,因为数据包的长度都相同)0x0d
是校验和(这是我的问题)CS
是连接ID(在我的测试中似乎总是01)ID
提前谢谢。我想只是描述中有个错误。看起来他们正在对报头和校验和之间的所有字节求和。校验和只是一个清除低8位的数字。因此,对于第一个示例,标头和校验和之间的所有字节之和为0x0313。或
0x0313 0000 0011 0001 0011
0x00ED 0000 0000 1110 1101
当它像那样排列时,您可以清楚地看到您将清零较低的8位并返回:
0x0400 0000 0100 0000 0000
您没有指定语言,但您也可以通过执行(0 XOR calculatedSum)+1快速计算自己的校验和。我认为描述中有一个错误。看起来他们正在对报头和校验和之间的所有字节求和。校验和只是一个清除低8位的数字。因此,对于第一个示例,标头和校验和之间的所有字节之和为0x0313。或
0x0313 0000 0011 0001 0011
0x00ED 0000 0000 1110 1101
当它像那样排列时,您可以清楚地看到您将清零较低的8位并返回:
0x0400 0000 0100 0000 0000
您没有指定语言,但您也可以通过执行(0 XOR calculatedSum)+1快速计算自己的校验和。如果您将标头、DataLength、CommandData和校验和中的所有十六进制数相加,则为1024 例如,下面是第二个示例的总和(我跳过了0x00): 屏幕截图(sum只是我编写的一个javascript函数,用于自动对十六进制值求和): 编辑:
它不必求和到1024,相反,如果它是有效的,它将求和到8个低位为0的数字,例如1024(1000000000)、768(1100000000)和1280(10100000000)。如果您将头中的所有十六进制数、数据长度、CommandData和校验和相加,则为1024 例如,下面是第二个示例的总和(我跳过了0x00): 屏幕截图(sum只是我编写的一个javascript函数,用于自动对十六进制值求和): 编辑: 它不一定要求和到1024,相反,如果它是有效的,它将求和到8个低位为0的数字,例如1024(1000000000)、768(1100000000)和1280(10100000000)。
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);
}
uint8\u-t-chksum(const-uint8\u-t*数据,大小长度)
{
尺寸i;
无符号整数chk=-1;
对于(i=0;i
你
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);
}
uint8\u-t-chksum(const-uint8\u-t*数据,大小长度)
{
尺寸i;
无符号整数chk=-1;
对于(i=0;i
为了好玩,我将此作为使用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;
}
为了好玩,我将此作为使用BoostSpirit(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;
}
啊哈!我找到了。它包括标题。啊哈!我找到了。它包含标题。这是解决方案,但它不是完全有效的。我得到的是768、1024和1280的总和。你能把总和不正确的数据包发出去吗?也许他们在运输途中被损坏了。您提供的所有示例似乎都有效。(参见我帖子中添加的屏幕截图)768、1024和1280都是有效的。当校验和正常时,字节和校验和字节之和的低8位将为0。我知道。这就是我写“这就是解决方案”的原因。请注意,您的评论的最后一句不是真的。校验和字节将不是0。(字节总和&0xFF)将为零。这就是为什么校验和字节用于:使和为零。这是解决方案,但并不完全有效。我得到的是768、1024和1280的总和。你能把总和不正确的数据包发出去吗?也许他们在运输途中被损坏了。您提供的所有示例似乎都有效。(参见我帖子中添加的屏幕截图)768、1024和1280都是有效的。当校验和正常时,字节和的低8位