UNIX网络编程卷1:套接字联网-第3章:套接字编程-readn,writen函数

前端之家收集整理的这篇文章主要介绍了UNIX网络编程卷1:套接字联网-第3章:套接字编程-readn,writen函数前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

既然我们已经有了系统提供的接口read和write,为什么还需要readn writen 和readline呢?

因为字节流套接字上调用read或write输入和输出的字节数可能比请求的数量少,然而这不是出错状态(在我的另一篇博文:点击此处 已经指出),为了预防万一,不让实现返回一个不足的字节计数值,unix网络编程作者就封装了以下函数

在/unpv13e/lib 下unp.h中有如下申明
ssize_t readn(int,void *,size_t);

ssize_t writen(int,const void *,size_t);


在lib/下 vim readn.c

/* include readn */
#include        "unp.h"

ssize_t                                         /* Read "n" bytes from a descriptor. */
readn(int fd,void *vptr,size_t n)
{
        size_t  nleft;
        ssize_t nread;
        char    *ptr;  //我们人工的加了一层缓冲区,用于存read从fd处读到的指定字节
        ptr = vptr;
        nleft = n;
        while (nleft > 0) {

//下面操作刚接触网络编程的人可能不太理解,read默认是阻塞函数,也就是说应用进程可能会阻塞到此处(如资源数据还没准备到位),对于阻塞函数,我们需要仔细分析每一种
//返回值情况,从而一一处理,read返回值的三种状态,正整数,0,,1,以后我会专门以源码出发的角度详解)

  if ( (nread = read(fd,ptr,nleft)) < 0) {
            if (errno == EINTR) /*表示此调用被信号中断*/
                 nread = 0; /* and call read() again */ 
            else 
                return(-1); /*错误发生,返回-1,文件读写位置无法预期,只能返回-1(表示错误退出 */
         } else if (nread == 0) /*读到文件尾部或者对端执行关闭操作*/ 
                    break; /* EOF */
               nleft -= nread;
               ptr   += nread;
        }
        return(n - nleft);              /* return >= 0 */
}

/* end readn */
/*包裹函数*/
ssize_t
Readn(int fd,void *ptr,size_t nbytes)
{
        ssize_t         n;

        if ( (n = readn(fd,nbytes)) < 0)
                err_sys("readn error");
        return(n);
}
//readn函数:从一个描述符读n字节



在lib/ 下 vim writen.c

/* include writen */
#include        "unp.h"

ssize_t                                         /* Write "n" bytes to a descriptor. */
writen(int fd,const void *vptr,size_t n)
{
        size_t          nleft;
        ssize_t         nwritten;
        const char      *ptr;

        ptr = vptr;
        nleft = n;
        while (nleft > 0) {
                if ( (nwritten = write(fd,nleft)) <= 0) {
                        if (nwritten < 0 && errno == EINTR)  //被信号中断
                                nwritten = 0;           /* and call write() again */
                        else
                                return(-1);                     /* error,文件读写位置无法预期*/
                }
                nleft -= nwritten;
 ptr += nwritten;
 }
 return(n);
}
/* end writen */

/*包裹函数*/
void
Writen(int fd,size_t nbytes)
{
 if (writen(fd,nbytes) != nbytes)
 err_sys("writen error");
}

猜你在找的Bash相关文章