流协议与粘包,粘包差生的原因,粘包处理方案,4.readn/writen 的封装

1. 流协议与粘包
  TCP是基于字节流的传输服务,这意味着TCP传送的数据之间是没有边界的。
  UDP是基于消息的传输服务,它传输的是报文(数据报),是具有边界的。
  字节流传输时不能保证对方接受到的是一个消息还是多个消息,所以会产生粘包问题
  基于消息传输的协议来说,能够保证对等方一次读操作只能返回一条消息。
   
2.粘包差生的原因
   a.应用层的缓冲区大小超过套接口发送缓冲区大小(消息被分割)
   b.TCP传输受最大段MSS限制
   c.链路层传输的数据受最大传输单元MTU的限制
   d.流量控制,拥塞控制,延迟发送等机制
 
3.粘包处理方案
  本质上在应用层自己维护消息与消息的边界
  a.定长报(以定长的形式发送,对等方也以定长的形式接受)
  b.包尾部加\r\n(ftp协议就用到这种方式,如果消息中本来含有\r\n 可能用到转义方式解决)
  c.包头加上包体的长度
  d.可以设计更复杂的应用层协议
 
   
4.readn/writen 的封装   
  接受/发送确切数据的操作
  方法一:定长报文(在没有接受或者发送到指定长度的报文一直接受或者发送)

       缺点:增加网络的负担假如固定长度为1024,实际有效的数据只有5个字符

//要接受确定的count字节数
ssize_t readn(int fd,void *buf,size_t count) //size_t是无符号的整数ssize_t是有符号的整数
{ 
    size_t nleft =count ;//剩余的字节数
    size_t nread;        //已经接受的字节数
    char *bufp =(char *)buf;
    while(nleft > 0)
    {
        if(nread =read(fd,bufp,nleft)<0)
        {
            if(errno ==EINTR ) //全局变量errno值为EINTR 表示信号被中断了.,这种情况不认为是失败了
            {
                continue;
            }
            else
            {
                return -1;
            }
        }
        else if(nread == 0) //说明对等方关闭了
        {
            return count - nleft ;
        }
        else
        {
            bufp  +=nread;
            nleft -=nread;
        }
    }
    return count;
}

ssize_t writen(int fd,const void *buf,size_t count)
{
    size_t nleft =count ;//剩余的字节数
    ssize_t nwriten;     //已发送的字节数
    char *bufp =(char *)buf;
    while(nleft > 0)
    {
        if(nwriten =read(fd,bufp,nleft)<0)
        {
            if(errno ==EINTR ) //全局变量errno值为EINTR 表示信号被中断了.,这种情况不认为是失败了
            {
                continue;
            }
            else
            {
                return -1;
            }
        }
        else if(nwriten == 0) //说明什么都没有发送
        {
            continue;
        }
        else
        {
            bufp  +=nwriten;
            nleft -=nwriten;
        }
    }
    return count;
}


  方法二:加上传输数据的长度
  struct packet
  {
      int len;         //报头,在接受时先接受报头,确定包体的实际大小
      char buff[1024]; //报体
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值