我有一些套接字连接代码,它使用boost :: asio从套接字中读取前5个字符,从中可以确定发送的字符串是否使用zlib库进行压缩。我目前正在做的项目是重写现有的东西,所以我采用了一些现有的代码并使它更像C ++,而不是C.但是在代码中它调用了memcpy
,我似乎完全是多余的,但是如果那个调用不在那里,对async_read
的调用永远不会被调用,这是我没有得到的。为什么?这个memcpy
电话的目的是什么?为什么它需要在所有指标中出现?
/*check for zlib compression and then call handle_read_s which gets the rest of the data and decompresses if necessary.*/
/// buff is a vector<char>
/// tempbuff is a char[5]
void tcp_connection::handle_read(const boost::system::error_code& err, size_t bytes_transferred, endpoint_ptr ptr)
{
unsigned long maxsz = 1024; //0xffffffff;
size_t size = 1024;
b_zlib = false;
if (!err || err == boost::asio::error::message_size)
{
if (bytes_transferred >= 4)
{
if (tempbuff[0] == 'Z')
b_zlib = true;
//Remove 4 bytes & remove memcpy
memcpy(&maxsz, &tempbuff[1], 4); //removing this makes my code unworkable, I don't get it?
buff.resize(maxsz); //passing anything else here also kills it?!!
boost::asio::async_read(socket_, boost::asio::buffer(buff), boost::bind(&tcp_connection::handle_read_s, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, ptr));
}
}
}
答案 0 :(得分:4)
此代码告诉您所需缓冲区的大小。
memcpy(&maxsz, &tempbuff[1], 4);
此代码正在调整缓冲区的大小
buff.resize(maxsz);
答案 1 :(得分:2)
memcpy
的目的是使代码不可移植,
并在代码编译到另一个代码时引入尴尬的错误
机。它的作用是将maxsz
设置为某个值,具体取决于
你刚刚读到了什么。价值是否正确取决于
机。 (如果我可以信任这些名字,那么也是未定义的
行为bytes_transferred
等于4.并且会有
如果您移植到unsigned
long
为64位的机器,则为未定义的行为。)
根据协议,您应该使用:
maxsz = static_cast<unsigned char>(tempbuff[1])
| (static_cast<unsigned char>(tempbuff[2]) << 8)
| (static_cast<unsigned char>(tempbuff[3]) << 16)
| (static_cast<unsigned char>(tempbuff[4]) << 24);
或
maxsz = (static_cast<unsigned char>(tempbuff[1]) << 24)
| (static_cast<unsigned char>(tempbuff[2]) << 16)
| (static_cast<unsigned char>(tempbuff[3]) << 8)
| static_cast<unsigned char>(tempbuff[4]);
(将tempbuff
的类型更改为unsigned char[5]
,您可以
消除static_cast
。这可能需要其他更改
然而,在其他地方。)
此外,第二个if
几乎肯定应该是:
if ( bytes_transferred > 4 )
,而非>=
(或>= 5
)。或者名称不应该是
bytes_transferred
。您的代码访问所有五个字节
tempbuff
。 (就此而言,我怀疑如果
bytes_transferred
不完全是5,事情会搞砸。)
答案 2 :(得分:1)
该代码与以下内容基本相同,我认为您看起来比较熟悉:
maxsz = *reinterpret_cast<unsigned long*>(&tempBuff[1]);
// or possibly, depending on endianness, ...
maxsz = ntohl(*reinterpret_cast<unsigned long*>(&tempBuff[1]));
不同之处在于,以您的代码执行方式使用memcpy
符合标准,而使用此处所示的reinterpret_cast
会调用undefined behavior。
答案 3 :(得分:0)
我认为tempbuff的前4个字节是缓冲区的大小,因此它读取前4个字节,确定缓冲区的大小,然后将缓冲区的大小调整为该大小。在像ildjarn这样的reinterpret_cast中执行此操作将使其更像C ++。