赞
踩
使用TCP协议编写应用程序时,需要考虑一个问题:TCP协议是无消息边界的,即不能保证来自单个Send方法的数据能被单个Receive方法读取。
解决办法:
1. 发送固定长度的消息。这种方适用于信息长度固定的场合。
2. 将消息长度与消息一起发送。
3. 使用特殊标记分隔消息。
先前项目中使用方法2:
void TcpConnection::Recv() {
socket_.Recv(std::bind(&TcpConnection::OnRead, shared_from_this(), std::placeholders::_1, std::placeholders::_2));
}
void TcpConnection::OnRead(const ErrorCode& e, uint32 len) {
CHECK_ERROR(e);
if (cb_.OnRead) {
uint8 *buf = socket_.GetBuf();
auto cur_pos = recv_buf_.size();
recv_buf_.resize(cur_pos + len);
memcpy(recv_buf_.data() + cur_pos, buf, len);
uint32 proc_len = cb_.OnRead(shared_from_this(), &recv_buf_[0], (uint32)recv_buf_.size());
if (proc_len > 0) {
recv_buf_.erase(recv_buf_.begin(), recv_buf_.begin() + proc_len);
}
}
Recv();
}
uint32 Client::onRead(const ConnectionPtr& conn, const uint8* buf, uint32 len)
{
uint32 total_len = 0;
int64 len_left = len;
while (len_left > sizeof(PacketHeader)) {
PacketHeader *p = (PacketHeader *)buf;
if (p->len > MAX_PKT_SIZE)
{
LOGE("Recv packet overflow, shutdown this connection");
conn->Shutdown();
return total_len;
}
uint32 cur_len = p->len + sizeof(PacketHeader);
if (len_left < cur_len) {
break;
}
handleData(p->buf, p->len);
total_len += cur_len;
buf += cur_len;
len_left -= cur_len;
}
return total_len;
}

void VectorFunc(std::vector<int> &v) {
v[0]; // A
v.at(0); // B
}
如果v非空,A行和B行没有任何区别。如果v为空,B行会抛出std::out_of_range异常,A行的行为未定义。
c++标准不要求vector::operator[]进行下标越界检查,原因是为了效率,总是强制下标越界检查会增加程序的性能开销。设计vector是用来代替内置数组的,所以效率问题也应该考虑。不过使用operator[]就要自己承担越界风险了。
如果需要下标越界检查,请使用at。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。