Skip to content

Latest commit

 

History

History
125 lines (115 loc) · 3.08 KB

10.4.md

File metadata and controls

125 lines (115 loc) · 3.08 KB

10.4 用RIO健壮的读写

介绍

RIO包其实来源于UNPV1中的readline,readn和write函数,是为了健壮的(Robust)I/O, 它会自动处理I/O中的不足值的问题

RIO提供两种函数:

  • 无缓冲的输入输出函数 从网络读写二进制数据
  • 带缓冲的输入函数 从文件中读取文本行和二进制数据而且线程安全

RIO的无缓冲输入输出函数

ssize_t  rio_readn(int fd, void *usrbuf, size_t n)
{
    size_t nleft = n; 
    ssize_t nread;
    char *bufp = usrbuf;
    while(nleft > 0)
    {
        if(nread = read(fd,bufp,nleft) < 0) //每次读取剩下的字节
        {
            if( errno == EINTR) //被信号中断
                nread = 0; //归零
            else
                return -1;
        }
        else if( nread == 0) //遇到EOF 跳出循环
                break;
        nleft -= nread;
        bufp += nread;
    }
    return (n - nleft);  
}


ssize_t rio_writen(int fd, void *usrbuf,size_t n)
{
    size_t nleft = n;
    ssize_t nwritten;
    char *bufp = usrbuf;
    while(nleft > 0)
    {
        if(nwritten = write(fd,bufp,nleft) < 0)
        {
            if(errno == EINTR)
                nwritten = 0;
            else
                return -1;
        }
        nleft -= nwritten;
        bufp += nwritten;
    }
    return n;
}

RIO中带缓冲的输入函数

#define RIO_BUFSIZE 8192
typedef struct 
{
    int rio_fd;
    int rio_cnt;
    char *rio_bufptr;
    char rio_buf[RIO_BUFSIZE];
};

void rio_readinitb(rio_t *rp, int fd)
{
    rp->rio_fd = fd;
    rp->rio_cnt = 0;
    rp->rio_bufptr = rp->rio_buf;
}
//
static ssize_t rio_read(rio_t *rp, char *usrbuf, size_t n)
{
    int cnt;
    while(rp->rio_cnt <= 0) //buf为空
    {
        rp->rio_cnt = read(rp->rio_fd, rp->rio_buf, sizeof(rp->rio_buf));
        if( rp->rio_cnt < 0)
        {
            if( errno != EINTR)
                return -1;
        }
        else if( rp->rio_cnt == 0)  //EOF 结尾
            return 0;
        else
            rp->rio_bufptr = rp->rio_buf;
    }
    cnt = n;
    if( rp->rio_cnt < n)
    {
        cnt =rp->rio_cnt;
    }
    memcpy(usrbuf, rp->rio_bufptr,cnt);
    rp->rio_bufptr += cnt;
    rp->rio_cnt -= cnt;
    return cnt;
}
ssize_t rio_readlineb(rio_t *rp,void *usrbuf,size_t maxlen)
{
    int n,rc;
    char c,*bufp = usrbuf;
    for(n=1; n < maxlen; n++)
    {
        if((rc = rio_read(rp,&c,1)) == 1)
        {
            *bufp++ = c;
            if( c == '\n')
                break;
        }
        else if( rc == 0)
        {
            if( n == 1)
                return 0;
            else
                break;
        }
        else
            return -1;
    }
    *bufp = 0;
    return 0;
}