粘包问题的表述,产生,常见的解决方案
粘包可能出现的现象:Host A 发送给 Host B 的情况
粘包可能出现的产生的原因分析:
粘包常见的解决方案:
定长包的实现
确定:增加了网络负担,发送一些不必要的数据长度
size_t readn(int fd,void * buf,size_t count)
{
size_t nleft = count;
size_t nread = -1;
char * bufp = (char*)buf;
while (nleft > 0)
{
if ((nread = read(fd, bufp, nleft)) < 0) //阻塞
{
if (errno == EINTR) //发生信号中断
{
continue;
}
return -1; //其他的错误返回 -1
}
else if (nread == 0)
{
return count - nleft; //表示读取到的字符
}
bufp += nread;
nleft -= nread;
}
return count;
}
//写入固定长度的数据
size_t writen(int fd,const void * buf,size_t count)
{
size_t nleft = count;
size_t nwriten = -1;
char * bufp = (char*)buf;
while (nleft > 0)
{
if ((nwriten = write(fd, bufp, nleft))< 0) //write 一般不会阻塞
{
if (errno == EINTR) //发生信号中断
{
continue;
}
return -1; //其他的错误返回 -1
}
else if (nwriten == 0)
{
continue; //表示读取到的字符
}
bufp += nwriten;
nleft -= nwriten;
}
return count;
}
第二种方式 包头加包体方式
第一步接受包体的长度
第二步接受包体
int ret = readn(conn, &recvbuf.len, 4); //第一步接受四个字节
if ( ret == -1)
{
ERR_EXIT("read");
}
else if (ret < 4) //对方关闭
{
printf("client close\n");
break;
}
//进一步接受包体
n = ntohl(recvbuf.len);
ret = readn(conn, recvbuf.buf, n);
if ( ret == -1)
{
ERR_EXIT("read");
}
else if (ret < n) //对方关闭
{
printf("client close\n");
break;
}
fputs(recvbuf.buf, stdout);
writen(conn, &recvbuf, 4+n);