网络编程(三)

本文深入探讨了网络通信中常见的粘包问题,分析其产生原因,并提供了两种实用的解决方案:一是通过定长包实现,虽然增加网络负担,但确保数据完整;二是采用包头加包体方式,先接收包体长度再接收包体,有效避免粘包现象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

粘包问题的表述,产生,常见的解决方案

粘包可能出现的现象: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);

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值