1.为什么要使用readline函数?首先我们先考虑一下网络字节流传递消息的时候的黏包问题,我们之前的解决办法是将存放消息的buf定义成一个结构体,里面有一个len成员用来记录下一次我要发送多少个字节的消息。我们可以再想一种方法,我们把消息之间用一个标识符隔开,这样每个包之间就可以分离开来。比如我们可以像ftp那样用一个‘\r\t‘隔开。
2.使用readline需要注意的地方:首先我们先用recv函数将套接字里面的消息先偷出来,所谓偷,就是直接复制过来,而不像read函数那样直接把消息剪切过来。先复制过来看看有没有’\n‘字符,如果没有的话就得readn进来。如果有的的话就直接读到缓冲区就可以了。
代码:
ssize_t readline(int fd,void *buf,size_t len ){
ssize_t ret;
ssize_t nread = 0;
size_t nleft = len;
char * ptr = buf;
while(1){
ret = recv(fd,ptr,nleft,MSG_PEEK); //recv函数将套接字里面的消息拷贝出来,它并不是将消息剪切过来。
if(ret < 0)
ERR_EXIT("readn by recv");
if(ret == 0 ){
printf("close the socket");
break;
}
int i;
for(i=0;i<ret;i++){ //写一个for循环,看看刚刚偷窥过来的消息有没有'\n'。
if(ptr[i] == '\n')
{
readn(fd,ptr,i+1); //如果有'\n'那就直接readn到缓冲区里面就可以了。
nread += i+1;
return nread;
}
}
readn(fd,ptr,ret); //如果没有'\n',那就直接readn到缓冲区,再进行下一次拷贝和检测。
nleft -= ret; //不要忘了将nleft和ptr和nread更新。
ptr += ret;
nread += ret;
}
return nread;
}