https://github.com/ckliufuchao/fuck_tcp
解决 TCP 粘包和拆包问题的代码架构如下:
char tmp[]; Buffer buffer; // 网络循环:必须在一个循环中读取网络,因为网络数据是源源不断的。 while(1){ // 从TCP流中读取不定长度的一段流数据,不能保证读到的数据是你期望的长度 tcp.read(tmp); // 将这段流数据和之前收到的流数据拼接到一起 buffer.append(tmp); // 解析循环:必须在一个循环中解析报文,应对所谓的粘包 while(1){ // 尝试解析报文 msg = parse(buffer); if(!msg){ // 报文还没有准备好,糟糕,我们遇到拆包了!跳出解析循环,继续读网络。 break; } // 将解析过的报文对应的流数据清除 buffer.remove(msg.length); // 业务处理 process(msg); } }
这段代码是终极地解决 TCP 粘包和拆包问题的代码!
这段代码之所以正确,是因为它包含了两个循环:网络循环和解析循环。
网络循环用于从 TCP socket 中读取流式数据,每一次读取到的数据的长度是不可预期,也就是,读取到的数据长短不一,无法保证,这就是所谓“流式”引出的问题。
而解析循环的功能是从拼接后流数据中,尝试解析出多个报文。注意,是多个报文,不是一个。因为所谓的粘包问题存在,所以可能是多个,而不是一个。如果解析不成功,那说明是遇到了拆包问题,我们继续读网络数据。
|