封装readn

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <unistd.h>
  5 #include <sys/types.h>
  6 #include <sys/stat.h>
  7 #include <fcntl.h>
  8 #include <sys/wait.h>
  9 #include <errno.h>
 10 #define ERR_EXIT(m)  11     do {  12         perror(m); 13         exit(EXIT_FAILURE); 14     }while(0)
 15
 16 #define BUFFERSIZE 65536  //缓冲区大小
 17
 18 typedef struct                  //缓冲区封装为一个结构体
 19 {
 20     int fd_; //fd
 21     int cnt_; //缓冲区可用的字节数
 22     char *ptr_; //指向缓冲区可用的第一个字节
 23     char buffer_[BUFFERSIZE]; //缓冲区
 24 } rio_t;
 25
 26 //初始化IO系统
 27 void rio_init(rio_t *rp, int fd)
 28 {
 29     rp->fd_ = fd;
 30     rp->cnt_ = 0;
 31     rp->ptr_ = rp->buffer_;
 32     memset(rp->buffer_, 0, BUFFERSIZE);
 33 }
 34
 35 //用来替换read
 36 ssize_t rio_read(rio_t *rp, char *usrbuf, size_t n)
 37 {
 38
 39     //缓冲区为空时,执行read操作
 40     while(rp->cnt_ <= 0)
 41     {
 42         ssize_t nread = read(rp->fd_, rp->buffer_, BUFFERSIZE);
 43         if(nread == -1)
 44         {
 45             if(errno == EINTR)
 46                 continue;
 47             return -1;  //ERROR
 48         }
 49         else if(nread == 0)
 50             return 0;
 51
 52         //正常读取
 53         rp->cnt_ = nread;
 54         rp->ptr_ = rp->buffer_; //重置指针
 55     }
 56
 57     //现有库存和用户要求的数量 取较小者
 58     int cnt = (rp->cnt_ < n) ? rp->cnt_ : n;
 59     memcpy(usrbuf, rp->ptr_, cnt);
 60     rp->ptr_ += cnt;
 61     rp->cnt_ -= cnt;
 62
 63     return cnt;  //成功读取的字节数
 64 }
 65
 66
 67 ssize_t rio_readn(rio_t *rp, void *buf, size_t count)
 68 {
 69     size_t nleft = count;  //剩余的字节数
 70     ssize_t nread; //用作返回值
 71     char *bufp = (char*)buf; //缓冲区的偏移量
 72
 73     while(nleft > 0)
 74     {
 75         //不再执行read系统调用
 76         nread = rio_read(rp, bufp, nleft);
 77         if(nread == -1)
 78         {
 79             if(errno == EINTR)
 80                 continue;
 81             return -1; // ERROR
 82         }
 83         else if(nread == 0) //EOF
 84             break;
 85
 86         nleft -= nread;
 87         bufp += nread;
 88     }
 89
 90     return (count - nleft);
 91 }
 92
 93 ssize_t rio_readline(rio_t *rp, char *usrbuf, size_t maxlen)
 94 {
 95     int i; //计数
 96     int nread;
 97
 98     char *bufp = usrbuf;
 99     char c; //暂存字符
100
101     for(i = 0; i < maxlen - 1; ++i)
102     {
103         if((nread = rio_read(rp, &c, 1)) == -1)
104             return -1;
105         else if(nread == 0) //EOF
106         {
107             if(i == 0)
108                 return 0;
109             break;
110         }
111
112         *bufp++ = c; //放入usrbuf
113         if(c == ‘\n‘) //碰到换行符直接退出循环
114             break;
115     }
116     *bufp = ‘\0‘;
117     return i; //返回读取的字节数
118 }
119
120
121 ssize_t rio_writen(int fd, const void *buf, size_t count)
122 {
123     size_t nleft = count;
124     ssize_t nwrite;
125     const char *bufp = (const char*)buf;
126
127     while(nleft > 0)
128     {
129         nwrite = write(fd, bufp, nleft);
130         if(nwrite <= 0) // ERROR
131         {
132             if(nwrite == -1 && errno == EINTR)
133                 continue;
134             return -1;
135         }
136
137         nleft -= nwrite;
138         bufp += nwrite;
139     }
140
141     return count;
142 }
143
144
145 int main(int argc, const char *argv[])
146 {
147     int fd = open("test.txt", O_RDONLY);
148     if(fd == -1)
149         ERR_EXIT("open test.txt");
150     rio_t rio;
151     rio_init(&rio, fd);
152
153     char buf[1024] = {0};
154     // rio_readn(&rio, buf, 3);
155     // printf("%s\n", buf);
156
157     while(rio_readline(&rio, buf, sizeof buf) > 0)
158     {
159         printf("%s", buf);
160     }
161
162     close(fd);
163
164     return 0;
165 }

ReadFile.h

 1 #include "ReadFile.h"
 2
 3
 4 ReadFile::ReadFile(std::string filename)
 5 : fd_(-1),
 6   filename_(std::move(filename))
 7 {
 8
 9 }
10
11 ReadFile::~ReadFile()
12 {
13     if(fd_ != -1)
14         close();
15 }
16
17 bool ReadFile::open()
18 {
19     fd_ = ::open(filename_.c_str(), O_RDONLY);
20     if(fd == -1)
21         return false;
22
23     buffer_.reset(new RobustIO(fd_));
24     return true;
25 }
26
27 void ReadFile::close()
28 {
29     ::close(fd_);
30     fd_ = -1;
31 }

ReadFile.cpp

 1 #ifndef READ_FILE_H_
 2 #define READ_FILE_H_
 3
 4 #include "NonCopyable.h"
 5 #include <string>
 6
 7 class ReadFile : NonCopyable
 8 {
 9 public:
10     ReadFile(std::string filename);
11     ~ReadFile();
12     bool open();
13
14     ssize_t read(char *usrbuf, size_t count);
15     ssize_t readn(char *usrbuf, size_t count);
16     ssize_t readLine(char *usrbuf, size_t maxlen);
17
18     int readInt();   //32 "3211111"
19     int32_t readInt32();
20     int64_t readInt64();
21     string readLine();
22
23     void close();
24
25 private:
26     int fd_;
27     std::unique_ptr<RobustIO> buffer_;
28     const std::string filename_; //文件名
29 };
30
31
32 #endif //READ_FILE_H_

缓冲区也封装成类

 1 #ifndef ROBUST_IO_H
 2 #define ROBUST_IO_H
 3
 4 #include "NonCopyable.h"
 5 #include <unistd.h>
 6
 7 class RobustIO : NonCopyable
 8 {
 9 public:
10     RobustIO(int fd);
11     ssize_t readn(char *usrbuf, size_t n);
12     ssize_t readLine(char *usrbuf, size_t maxlen);
13     ssize_t writen(int fd, const void *buf, size_t count);
14 private:
15     ssize_t read(char *usrbuf, size_t n);
16
17     static const int kBufferSize = 65536;
18
19     int fd_; //fd
20     int cnt_; //缓冲区可用的字节数
21     char *ptr_; //指向缓冲区可用的第一个字节
22     char buffer_[kBufferSize]; //缓冲区
23 };
24
25
26 #endif //ROBUST_IO_H
#include "RobustIO.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <errno.h>
#define ERR_EXIT(m)     do {         perror(m);        exit(EXIT_FAILURE);    }while(0)

//const int RobustIO::kBufferSize = 65536;

RobustIO::RobustIO(int fd)
{
    fd_ = fd;
    cnt_ = 0;
    ptr_ = buffer_;
    ::memset(buffer_, 0, kBufferSize);
}

ssize_t RobustIO::read(char *usrbuf, size_t n)
{
    //缓冲区为空时,执行read操作
    while(cnt_ <= 0)
    {
        ssize_t nread = ::read(fd_, buffer_, kBufferSize);
        if(nread == -1)
        {
            if(errno == EINTR)
                continue;
            return -1;  //ERROR
        }
        else if(nread == 0)
            return 0;

        //正常读取
        cnt_ = nread;
        ptr_ = buffer_; //重置指针
    }

    //现有库存和用户要求的数量 取较小者
    int cnt = (cnt_ < n) ? cnt_ : n;
    ::memcpy(usrbuf, ptr_, cnt);
    ptr_ += cnt;
    cnt_ -= cnt;

    return cnt;  //成功读取的字节数
}

ssize_t RobustIO::readn(char *usrbuf, size_t count)
{
    size_t nleft = count;  //剩余的字节数
    ssize_t nread; //用作返回值
    char *bufp = (char*)usrbuf; //缓冲区的偏移量

    while(nleft > 0)
    {
        //不再执行read系统调用
        nread = this->read(bufp, nleft);
        if(nread == -1)
        {
            if(errno == EINTR)
                continue;
            return -1; // ERROR
        }
        else if(nread == 0) //EOF
            break;

        nleft -= nread;
        bufp += nread;
    }

    return (count - nleft);
}

ssize_t RobustIO::readLine(char *usrbuf, size_t maxlen)
{
    int i; //计数
    int nread;

    char *bufp = usrbuf;
    char c; //暂存字符

    for(i = 0; i < maxlen - 1; ++i)
    {
        if((nread = this->read(&c, 1)) == -1)
            return -1;
        else if(nread == 0) //EOF
        {
            if(i == 0)
                return 0;
            break;
        }

        *bufp++ = c; //放入usrbuf
        if(c == ‘\n‘) //碰到换行符直接退出循环
            break;
    }
    *bufp = ‘\0‘;
    return i; //返回读取的字节数
}

ssize_t RobustIO::writen(int fd, const void *buf, size_t count)
{
    size_t nleft = count;
    ssize_t nwrite;
    const char *bufp = (const char*)buf;

    while(nleft > 0)
    {
        nwrite = write(fd, bufp, nleft);
        if(nwrite <= 0) // ERROR
        {
            if(nwrite == -1 && errno == EINTR)
                continue;
            return -1;
        }

        nleft -= nwrite;
        bufp += nwrite;
    }

    return count;
}
时间: 2024-08-24 22:28:27

封装readn的相关文章

Linux组件封装(八)——Socket的封装

我们要封装Socket,首先我们需要了解Socket需要哪些要素: 1) 首先,一个套接字创建后,需要绑定一块网卡的IP,以及连接的对口号,所以我们先封装InetAddr. 在class中,仅有的一个私有成员就是struct sockaddr_in类型的一个对象,我们需要将该对象的几种赋值与创建封装到类中,这样,我们仅需传递相应的IP与port即可获得一个addr. 在这里,我们为了方便获得该addr的IP及port,封装几个将addr转化为IP及port的函数,这样我们仅需调用函数即可. 然后

TCP之函数封装

本文所有函数皆是为实现 TCP之简单回传(二)   系列所封装的函数: 所有函数皆用C语言实现.函数以及注释如下: 头文件: //.h #ifndef SYSUTIL_H #define SYSUTIL_H #include <stdint.h> #include <sys/types.h> void nano_sleep(double val); //实现定时作用 ssize_t readn(int fd, void *buf, size_t count);//读取真实数据 ss

Linux网络编程(附1)——封装read、write

原打算实践简单的模型的时候,主要专注于主要的模型,先用UNIX I/O糊弄下,但是未封装的read和write用起来实在心累,还是直接用前辈们已经实现好的高级版本read.write. UNIX I/O   read.write #include<unistd.h> ssize_t read(int fd, void* buf, size_t n); 若成功则为读的字节数,若EOF则为0,若出错则为-1: ssize_t write(int fd, const void* buf, size_

Linux网络编程-readn函数实现

readn函数功能:在网络编程的读取数据中,通常会需要用到一个读指定字节才返回的函数,linux系统调用中没有给出,需要自己封装. readn实现代码: int readn(int fd, void *vptr, size_t n) { size_t nleft = n; //readn函数还需要读的字节数 ssize_t nread = 0; //read函数读到的字节数 unsigned char *ptr = (char *)vptr; //指向缓冲区的指针 while (nleft >

自己封装一个readline函数实现服务器客户端回射

实现的功能:一次只能读取一行,客户端输入之后,一回车,马上字符串传到服务器端并显示在终端,然后服务器端将字符串又传回给客户端. 服务器端可以接收多个客户端的连接请求,并fork一个子进程来进行服务. (1)封装一个只能访问套接字描述符的readline函数 (2)服务器端启动SO_REUSEADDR套接字选项,以便服务器端不必等待TIME_WAIT状态 这是服务器端代码: 1 #include<unistd.h> 2 #include<sys/types.h> 3 #include

0723------Linux基础----------文件 IO 之 read 和 write (readn 、writen、readline)

1. readn 和 writen 1.1 基础巩固: read 和 write 函数的返回值 1.1.1 read 函数原型为:ssize_t  read(int fd, void* buf, size_t count); (这里的 void *在标准 C 中表示通用指针即任意类型的指针都可以对它赋值,ssize_t 是有符号整数)它的返回值如下: a)成功返回读取的字节数,这里可能等于 count 或者小于 count (当 count > 文件 size 的时候,返回实际读到的字节数):

python学习 面向对象封装

from collectoins import namedtuplePoint=namedtuple('point',['x','y'])t1=Point(1,2)print(t1.x)print(t1.y)没有方法的类属性不会发生变化    定义简单 不能改变面向对象封装私有属性!!!私有方法!!!用装饰器描述的几个方法@property !!!@classmethod!!@staticmethod! 封装:class Teacher:     def __init__(self,name,p

python—面向对象的封装

封装 私有属性 class Teacher: __identifier = 'Teacher' #私有静态属性 def __init__(self,name,pwd) self.name = name self.__pwd = pwd #私有属性 内部使用,外部不能使用 def pwd(self): print(self.__pwd) alex = Teacher('alex','3714') alex.pwd() class Teacher: __identifier = 'Teacher'

dbutils封装对象,单列,一行一列(用)

基本用法:查找并封装对象与对象集合 public User findUserByNamePassword(String name,String password){ QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource()); String sql = "select * from user where name='"+name+"' and password = '"+password