[问题记录]——TCP粘包问题:客户端利用length接收数据

  • 产生的原因:TCP通信中数据包是连续、首尾相连的、没有边界的流形式,连续发送多个不同的文件时,接收端无法识别分开发送过来的多个数据。

  • 解决方案:

    1. 时间边界:延时发送。
    2. 空间边界:填空数据。
    3. 额外标志:如结束字符(a. 接收要额外解析识别; b. 内容不能再出现这个标记字符)。
    4. 自定义协议头:协议头传递重要的信息,如文件名、文件大小。

在使用第四种方法时,客户端根据协议头中的文件大小接收文件,一开始我使用这样的while循环接收文件。

size = head.length; //文件大小
while (size > 0)
{
	cnt = read(client_fd, r_buffer, RECVSIZE); //接收文件内容
    write(file_fd, r_buffer, cnt);
    size -= cnt;
}

出现了第二个文件无法正常接收的问题,经过一番排查,发现原因如下:

  • 根据文件大小接收文件时,如果判断条件是while(size>0),由于每次接收的大小n是固定RECVSIZE的,且后面跟着下一个文件的数据,这样会导致最后一次把下一个文件的数据(协议头)也接收了,经过size-=cnt后size小于0。这样虽然能使循环终止,但由于拿到了下一个文件的内容,导致接收的第一个和第二个文件都发生错误。

修改循环条件:

// int cnt1 = 0;
size = head.length;
while (size > sizeof(r_buffer))
{
    cnt = read(client_fd, r_buffer, RECVSIZE); //接收文件内容
    write(file_fd, r_buffer, cnt);
    size -= cnt;
    // cnt1 += cnt;
}
cnt = read(client_fd, r_buffer, size); //size此时不为0
// cnt1 += cnt;
// printf("DEBUG recvlen: %d\n", cnt1);

接收正常,问题解决!
[问题记录]——TCP粘包问题:客户端利用length接收数据

上一篇:深入理解InnoDB引擎底层存储和缓存原理


下一篇:删数问题 贪心算法