TCP 网络通信与粘包问题
TCP 是面向字节流的协议,这意味着它不保留消息边界。发送端写入的数据可能被拆分成多个数据包发送,也可能被合并后一次性接收。这导致接收端无法直接判断一个完整的'报文'何时结束。
例如,发送方连续发送两个请求,接收方可能只读到部分数据,或者将两个请求混在一起读取。这就好比往文件里放东西,如果不知道对方怎么放的,拿的时候就会出错。所以一旦我们要发送一些带有结构化的数据时,就必须制定协议,这样才能满足我们想要返回结构化数据的需求。
自定义应用层协议设计
由于 TCP 是字节流协议,一次 read() 可能读到半个数据,也可能读到多个数据。因此我们需要自定义协议来明确数据边界。
协议格式
我们采用'长度前缀'模式。协议的格式设计如下:
len\n
content\n
举个例子就是:
6\n10 + 5\n
总之就是如下的格式:|len| \n |content| \n
协议封装实现
为了简化开发,我们将编码和解码逻辑封装成工具函数。
Encode(封装报文)
std::string Encode(std::string &content) {
std::string s;
size_t len = content.size();
s += std::to_string(len);
s += "\n";
s += content;
s += "\n";
return s;
}
例如输入 10 + 20,就会变为 7\n10 + 20\n。
Decode(解析报文)
bool Decode(std::string &s, std::string *content) {
size_t left_pos = s.find("\n");
if (left_pos == std::string::npos) return false;
std::string content_len = s.substr(0, left_pos);
int len = std::stoi(content_len);
if (s.size() < content_len.size() + len + 2) ;
*content = s.(left_pos + , len);
s.(, content_len.() + len + );
;
}


