粘包问题
本质要在应用层维护消息与消息边界问题
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);