size_t readline(int sockfd, void *buf, size_t maxline) //封装的readline函数只能用于套接口,因为用recv函数来实现的 { int ret; int nread;// 接受到的字节数 char *bufp =(char*)buf; int nleft = maxline; while(1){ ret = recv_peek(sockfd, bufp, nleft);//利用bufp去偷窥数据,直到遇到'\n' if(ret < 0) return ret; else if(ret == 0) return ret; nread = ret; int i; for(i = 0; i < nread; i++){ if(bufp[i] == '\n'){ ret = readn(sockfd, bufp, i+1); if(ret != i+1) exit(EXIT_SUCCESS); return ret; } } if(nread > nleft){ exit(EXIT_SUCCESS); } nleft -= nread; ret = readn(sockfd, bufp, nread); if(ret != nread) exit(EXIT_SUCCESS); bufp += nread; } return -1; }
ssize_t SocketIO::readline( char *buf, size_t maxlen) { size_t nleft = maxlen-1; char * pbuf = buf; size_t total =0; ssize_t nread; while( nleft >0) { nread = recv_peek(pbuf,nleft); if( nread <=0) return nread; for( int i=0; i<nread; i++ ) { if( pbuf[i]=='\n') { size_t nsize = i+1; if( readn(pbuf, nsize)!= static_cast<ssize_t>(nsize)) return -1; pbuf += nsize; total +=nsize; *pbuf ='\0'; return total; } } if( readn(pbuf, nread) !=nread ) return -1; pbuf +=nread; total +=nread; nleft -=nread; } *pbuf='\0'; return maxlen -1; }
//先偷窥,然后再判断偷窥到的是否有\n; //return value: //value == -1 : error //value == 0 : client close //value > 0 : ok ssize_t readline(int sockfd, void *buf, size_t count) { char *p = buf; size_t nleft = count; ssize_t nread = 0; while (nleft > 0) { nread = recv_peek(sockfd, p, nleft); if (nread < 0) return nread; else if (0 == nread) { return 0; } //偷窥到了数据,查看是否有\n int ix = 0; int ret = 0; for (ix = 0; ix != ret; ++ix) { if (p[ix] == '\n') { ret = readn(sockfd, p, ix + 1); if (ret != ix +1) ERR_EXIT("readn"); return count; } } //偷窥到的数据中没有\n,先把数据全部取出,然后开始下一循环 ret = readn(sockfd, p, nread); if (ret != nread) ERR_EXIT("readn"); p += ret; nleft -= ret; } return count; }
ssize_t readline(int fd, void *buf, size_t maxsize) { size_t nleft = maxsize; size_t nread = 0; char *p = static_cast<char*>(buf); int ret; while(1) { ret = recv_peek(fd, p, nleft); if(ret == -1) return ret; else if(ret == 0) return ret; nread = ret; for(int i = 0; i < nread; i++) { if(p[i]=='\n') { ret = readn(fd, p, i+1); if(ret != i+1) exit(EXIT_FAILURE); return ret; } } if(nread > nleft) exit(EXIT_FAILURE); ret = readn(fd, p, nread); if(ret != nread) exit(EXIT_FAILURE); nleft -= nread; p += nread; } return -1; }
ssize_t readline(int sockfd, void *buf, size_t maxline) { int ret; int nleft = maxline; int nread; char *bufp = buf; int i; while (1) { ret = recv_peek(sockfd, bufp, nleft); if (ret < 0) return ret; if (ret == 0) return 0; nread = ret; for (i=0; i < nread; i++) { if (bufp[i] == '\n') { ret = readn(sockfd, bufp, i+1); if (ret != i+1) exit(EXIT_FAILURE); return ret; } } if (nread > nleft) exit(EXIT_FAILURE); ret = readn(sockfd, bufp, nread); if (ret != nread) exit(EXIT_FAILURE); bufp += nread; nleft -= nread; } }
//功能:按行读取文件,只要遇到\n就,读走数据,返回, //@buf 接收数据内存首地址 //@maxline 接收数据内存最大值 ssize_t readline(int sockfd, void *buf, size_t maxline) { int ret; int nread; char *bufp = buf; int nleft = maxline; while (1) { //读数据,但不把数据缓冲区清空 //成功:ret是报文的长度 ret = recv_peek(sockfd, bufp, nleft); if (ret < 0) return ret; else if (ret == 0) return ret; nread = ret; int i; for (i = 0; i < nread; i++) { //读数据,但不把数据缓冲区清空,避免了一个字节一个字节的读数据 //先利用recv的MSG_PEEK功能,预读数据,然后查找\n //根据\n的位置,根据指定长度,再真正的读数据 if (bufp[i] == '\n') { //将数据从缓存区读走 ret = readn(sockfd, bufp, i + 1); if (ret != i + 1) exit(EXIT_FAILURE); return ret; } } //若数据长度nread > 缓冲区最大长度maxline 退出 if (nread > nleft) exit(EXIT_FAILURE); //若没有\n 说明消息还没有结束,不是完整的一条消息,就把这些数据也读到buf缓冲区中。 //依此循环,直到遇到\n,把整个一行数据,全部读完,放入buf中 //bufp记录了每次需追加的位置 nleft -= nread; ret = readn(sockfd, bufp, nread); if (ret != nread) exit(EXIT_FAILURE); bufp += nread; //bufp每次跳到追加的末尾 } return -1; }
ssize_t readline(int sockfd,void *buf, size_t maxlen) { int ret = 0; int nread; int nleft = maxlen; char *bufp = buf; while(1) { ret = recv_peek(sockfd, bufp, nleft); if(ret < 0) { return ret; } else if(ret == 0) { return ret; } nread = ret; int i = 0; for(i=0; i<nread; i++) { if(bufp[i] == '\n') { ret = readn(sockfd, bufp, i+1); if(ret != i+1) { exit(EXIT_FAILURE); } return ret; } } if(nread > nleft) { exit(EXIT_FAILURE); } nleft -= nread; ret = readn(sockfd, bufp, nread); if(ret != nread) { exit(EXIT_FAILURE); } bufp += nread; } return -1; }
ssize_t readline(int sockfd, void *buf, size_t maxline) { int ret; int nread; char *bufp = buf; int nleft = maxline; //一行的最大能读取的字节数,当遇到‘\n’时停止,nleft表示剩余的字节数 while(1) { ret = recv_peek(sockfd, bufp, nleft); //偷窥缓冲区中的数据,并没有将数据移走 if(0 > ret) return ret; //函数小于0表示失败,这里不用对信号中断判断了,因为recv_peek函数已经判断过了 else if(0 == ret) //表示对方关闭了套接口 return ret; //返回0 nread = ret;//接收正常的话,数据传给nread int i; //接下来判断数据中有没有‘\n’ for(i = 0; i < nread; i++) { if('\n' == bufp[i]) { ret = readn(sockfd, bufp, i+1);//使用nread函数将缓冲区中的数据移走,数据长度为i+1,需要包括‘\n’ if(i+1 != ret) //如果读取的字节数不等于i+1,意味着失败了 exit(EXIT_FAILURE); return ret; //如果读取正确,那就直接返回ret } } //如果没有‘\n’,说明还不满一条消息,也将这些数据读出来放到指针所指向的缓冲中 if(nread > nleft) //nread使用recv_peek函数读取的,长度为left,所以不可能超过这个剩余的字节数 { printf("error : nread > nleft\n"); exit(EXIT_FAILURE); } nleft -= nread; //表示剩下多少字符 ret = readn(sockfd, bufp, nread); if(ret != nread)//如果数据数量不等于这么多是有问题的,因为已经从缓冲区中偷窥到了这么多数据,按道理应该可以读取到这么多数据 { printf("error : ret != nread\n"); exit(EXIT_FAILURE); } //读走了这么多字节,下一次偷窥的时候应该从bufp+nread的地址开始偷窥,继续判断有没有‘\n’ bufp += nread; //将数据都存在了bufp中 //从这里开始循环,不断的取数据,直到读到‘\n’为止 } return -1;//程序如果执行到这里,说明跳出了while循环,说明出错了 }
ssize_t readline(int sockfd,void *buf,size_t maxline) { int ret,i; int nread; char *bufp = (char *)buf; int nleft = maxline; //只要遇到\n就可以了 while(1) { ret = recv_peek(sockfd,bufp,nleft); if(ret < 0) { return ret; } else if(0 == ret) { return ret;//说明对等方可能关闭了 } //printf("echoserv recv_peek ret:%d\n",ret); nread = ret; for(i = 0;i < nread;++i) { if(bufp[i] == '\n') { //说明读取到了一行 //然后这里读取的话,由于设置了MSG_PEEK所以数据 //并没有移除 ret = readn(sockfd,bufp,i + 1); //printf("readn ret %d i + 1 %d\n",ret,i + 1); if(ret != i + 1) { printf("ret != i + 1\n"); exit(EXIT_FAILURE); } return (maxline - nleft) + ret; } } //这里说明没有读取到一行消息,所以需要暂时 //读出来放到缓冲区当中 if(nread > nleft) { printf("nread(%d) > nleft(%d)\n",nread,nleft); exit(EXIT_FAILURE); } nleft -= nread; ret = readn(sockfd,bufp,nread); if(ret != nread) {//因为已经明确了有nread长度的数据 printf("ret != nread"); exit(EXIT_FAILURE); } bufp += nread;//继续去看下一个数据直到有一行数据 } return -1; }
/** * readline - 按行读取数据 * @sockfd: 套接字 * @buf: 接收缓冲区 * @maxline: 每行最大长度 * 成功返回>=0,失败返回-1 */ ssize_t readline(int sockfd, void *buf, size_t maxline) { int nread; //一次IO读取的数量 int nleft; //还剩余的字节数 char *ptr; //存放数据的指针的位置 int ret; //readn的返回值 int total = 0; //目前总共读取的字节数 nleft = maxline-1; ptr = buf; while (nleft > 0) { //这一次调用仅仅是预览数据 //并没有真的把数据从缓冲区中取走 ret = recv_peek(sockfd, ptr, nleft); //注意这里读取的字节不够,绝对不是错误!!! if (ret <= 0) { return ret; } nread = ret; int i; for (i = 0; i < nread; ++i) { if (ptr[i] == '\n') { //这里才是真正的读取过程 ret = readn(sockfd, ptr, i + 1); if (ret != i + 1) { return -1; } total += ret; ptr += ret; *ptr = 0; return total; //返回此行的长度 '\n'包含在其中 } } //如果没有发现\n,这些数据应全部接收 ret = readn(sockfd, ptr, nread); if (ret != nread) { return -1; } nleft -= nread; total += nread; ptr += nread; } *ptr = 0; return maxline-1; }
ssize_t readline(int fd, void* usrbuf, size_t maxline) { char* buf = usrbuf; ssize_t nread; size_t nleft = maxline; int ret; int total = 0; while(nleft > 0) { //把数据读到缓冲区中 ret = recv_peek(fd, buf, nleft); if(ret <= 0) return ret; nread = ret; int i; //i从1到nread开始遍历,知道读到换行为止 for(i = 0; i < nread; ++i) { //如果buf[i]为换行,则读取i+1个字符, //return,读取一行成功 if(buf[i] == '\n') { ret = readn(fd, buf, i+1); if(ret != i+1) return -1; total += ret; return total; } } //如果for循环后运行到这里,说明没遇到换行 //读取readn字节的数据 ret = readn(fd, buf, nread); if(ret != nread) return -1; nleft -= nread; total += nread; buf += nread; } return maxline; }
ssize_t SocketIO::readline(char* usrbuf, size_t maxlen) { size_t nleft = maxlen -1; char* bufp = usrbuf; size_t total = 0;//读取的字节数 ssize_t nread; while(nleft > 0) { nread = recv_peek(bufp, nleft); if(nread <= 0) { return nread; } for(ssize_t index=0; index<nread; index++) { if(bufp[index] == '\n')//找到\n { size_t nsize = i + 1; if(readn(bufp, nsize)!=static_cast<ssize_t>(nsize)) { return -1; } else { bufp += nsize; total -= nsize; *bufp = 0; return total; } } } if(readn(bufp, nread) != nread)//未找到\n { return -1; } bufp += nread; total += nread; nleft -= nread; } *bufp = 0; return maxlen - 1; }
ssize_t readline(int sockfd, void *buf, size_t maxline) { int nread; int nleft; char *ptr; int ret; int total = 0; nleft = maxline -1; ptr = buf; while(nleft > 0) { ret = recv_peek(sockfd, ptr, nleft); if(ret <= 0) return ret ; nread = ret ; int i; for (i = 0; i < nread; i++) { if(ptr[i] == '\n') { ret = readn(sockfd, ptr, i + 1); if(ret != i+1) return -1; total += ret; ptr += ret; *ptr = 0; return total; } } ret = readn(sockfd, ptr, nread); if(ret != nread) return -1; nleft -= nread; total += nread; ptr += nread; } *ptr = 0; return maxline; }
ssize_t readline(int sockfd, void *buf, size_t maxline) { int ret; int nread; char *bufp = (char *)buf; int nleft = maxline; while(nleft > 0) { ret = recv_peek(sockfd, bufp, nleft); if(ret < 0) return ret; else if(ret == 0) return 0; nread = ret; int i; for(i=0; i<nread; i++){ if(bufp[i] == '\n') { ret = readn(sockfd, bufp, i + 1); if( ret != i+1) exit(-1); return ret; } } if(nread > nleft) exit(-1); nleft -= nread; ret = readn(sockfd, bufp, nread); if(ret != nread) exit(-1); bufp += nread; } return -1; }
ssize_t SocketIO::readline(char * buf, size_t maxlen) { size_t nleft = maxlen - 1; char * pbuf = buf; ssize_t nread; size_t total = 0; while(nleft > 0) { nread = recv_peek(pbuf, nleft); if(nread <= 0) return nread; int i; for(i = 0; i != nread; ++i) { //当找到'\n' if(pbuf[i] == '\n') { size_t nsize = i + 1; if(static_cast<ssize_t>(nsize) != readn(pbuf, nsize)) return -1; pbuf += nsize; total += nsize; *pbuf = 0; return total; } } //当没有找到'\n' if(readn(pbuf, nread) != nread) return -1; total += nread; pbuf += nread; nleft -= nread; } *pbuf = 0; return maxlen - 1; }
ssize_t readline(int fd, void *buf, size_t maxlen) { size_t nleft = maxlen - 1; char *bufp = (char *)buf; ssize_t total = 0; ssize_t nread; while (nleft > 0) { //recv+peek为预读取 nread = recv_peek(fd, bufp, nleft); if (nread <= 0) return nread; //检查此段内有无\n int i; for (i = 0; i < nread; ++i) { if (bufp[i] == '\n') { //找到\n后读取退出 size_t nsize = i + 1; if (readn(fd, bufp, nsize) != nsize) return -1; bufp += nsize; *bufp = '\0'; total += nsize; return total; } } //到此步说明没有找到\n,继续 if (readn(fd, bufp, nread) != nread) return -1; bufp += nread; total += nread; nleft -= nread; } //读取到最大长度,返回 *bufp = '\0'; return maxlen - 1; }
ssize_t readline(int sockfd, void *buf, size_t maxline) { int ret; int nread; char *bufp = (char*) buf; int nleft = maxline; while (1) { ret = recv_peek(sockfd, bufp, nleft); if (ret < 0) { ERR_EXIT("recv_peek"); } else if (ret == 0) { return ret; //客户端退出 } nread = ret; int i; for (i = 0; i < nread; i++) { if (bufp[i] == '\n') //有回车表示是完整一行,读取然后返回 { ret = read(sockfd, bufp, i + 1); if (ret != i + 1) ERR_EXIT("read"); return ret; } if (nread > nleft) ERR_EXIT("read"); } ret = read(sockfd, bufp, nread); //没回车表示还有剩余数据,读完不饭回 nleft -= nread; bufp += nread; } return -1; //程序不会走这一步,如果走这一步证明出错了 }