socket编程学习---(四)粘包问题readn writen

粘包问题

本质要在应用层维护消息与消息边界问题
1.定长包
2.包尾加\r\n
3.包头加上包体长度(包头定常,比如4字节)
4.更复杂的应用层协议

readn
ssize_t readn(int fd,void *buf,size_t count)
{
	size_t nleft = count; //剩余字节数
	ssize_t nread; //接收到的字节数
	char *bufp = (char *)buf;
	while(nleft > 0)
	{
	    if((nread = read(fd,bufp,nleft)) < 0)
	      {   if(errno == EINTR)
	               countinue;
	           return -1;
	      }
	     else if(nread == 0) //对方关闭
	           return count - nleft; 
	     bufp += nread;
	     nleft -= nread;
    }
    return count;
}
writen
ssize_t writen(int fd,const void *buf,size_t count)
{
	size_t nleft = count; //剩余字节数
	ssize_t nwritten; //写入的字节数
	char *bufp = (char *)buf;
	while(nleft > 0)
	{
	    if((nwritten = write(fd,bufp,nleft)) < 0)
	      {   if(errno == EINTR)
	               countinue;
	           return -1;
	      }
	     else if(nwritten == 0) 
	           countinue;
	     bufp += nwritten;
	     nleft -= nwritten;
    }
    return count;
}

客户端

struct packet{
	int len;  //包头
	char buf[1024];//包体
}

struct packet sendbuf;
struct packet recvbuf;
memset(&sendbuf,0,sizeof(sendbuf));
memset(&recvbuf,0,sizeof(recvbuf));

//这里获得sendbuf.buf.....

int n = strlen(sendbuf.buf);//获得包头
sendbuf.len = htonl(n); 
writen(sock,&sendbuf,4+n);//发送包头包体

int ret = readn(sock,&recvbuf.len,4);
if(ret == -1)
{
     ERR_EXIT("read");
}
else if(ret <4)
{
     printf("cli close");
     break;
}
n = ntohl(recvbuf.len);
ret = readn(sock,recvbuf.buf,n);
if(ret == -1)
{
     ERR_EXIT("read");
}
else if(ret <n)
{
     printf("ser close");
     break;
}
//printf

服务器端

struct packet recvbuf;
memset(&recvbuf,0,sizeof(recvbuf));
int ret = readn(conn,&recvbuf.len,4);
if(ret == -1)
{
     ERR_EXIT("read");
}
else if(ret <4)
{
     printf("cli close");
     break;
}
n = ntohl(recvbuf.len);
ret = readn(conn,recvbuf.buf,n);
if(ret == -1)
{
     ERR_EXIT("read");
}
else if(ret <n)
{
     printf("cli close");
     break;
}
//printf
writen(conn,&recvbuf,4+n);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值