本文我们来实现回射服务器的Buffer。

 

Buffer的实现

 

上节提到了非阻塞IO必须具备Buffer。再次将Buffer的设计描述一下:

这里必须补充一点,writeIndex指向空闲空间的第一个位置。

这里有三个重要的不变式

1. 0 <= readIndex <= writeIndex <= BUFFER_SIZE

2. writeIndex – readIndex 为可以从buffer读取的字节数

3. BUFFER_SIZE – writeIndex 为buffer还可以继续读取的字节数

还有一点,数据读取完毕之后,要重置下标为0

根据我设计的这个示意图,我利用结构体封装了一个Buffer,如下:

#ifndef BUFFER_H_
#define BUFFER_H_ #include <poll.h> #define BUFFER_SIZE 1024 typedef struct {
char buf_[BUFFER_SIZE];
int readIndex_; //读取数据
int writeIndex_; //写入数据
} buffer_t; void buffer_init(buffer_t *bt);
int buffer_is_readable(buffer_t *bt);
int buffer_is_writeable(buffer_t *bt);
int buffer_read(buffer_t *bt, int sockfd);
int buffer_write(buffer_t *bt, int sockfd); #define kReadEvent (POLLIN | POLLPRI)
#define kWriteEvent (POLLOUT | POLLWRBAND) #endif //BUFFER_H_

这里的buffer先采用固定长度,后期可以改为动态数组。

下面我们来实现Buffer的每个函数。

第一个是初始化,内存清零,下标都设置为0即可。

void buffer_init(buffer_t *bt)
{
memset(bt->buf_, 0, sizeof(bt->buf_));
bt->readIndex_ = 0;
bt->writeIndex_ = 0;
}

缓冲区是否可以读出数据,需要判断(writeIndex – readIndex)是否大于0

int buffer_is_readable(buffer_t *bt)
{
return bt->writeIndex_ > bt->readIndex_;
}

缓冲区是否可写,需要判断是否有空闲空间。

int buffer_is_writeable(buffer_t *bt)
{
return BUFFER_SIZE > bt->writeIndex_;
}

接下来是调用read函数,buffer从fd中读取数据,read的最后一个参数为buffer的剩余空间。

int buffer_read(buffer_t *bt, int sockfd)
{
int nread = read(sockfd, &bt->buf_[bt->writeIndex_], BUFFER_SIZE - bt->writeIndex_);
if(nread == -1)
{
if(errno != EWOULDBLOCK)
ERR_EXIT("read fd error");
return -1;
}
else
{
bt->writeIndex_ += nread;
return nread;
}
}

最后是输出操作,将buffer中的数据写入sockfd,write的最后一个参数为buffer现存的字节数。

int buffer_write(buffer_t *bt, int sockfd)
{
int nwriten = write(sockfd, &bt->buf_[bt->readIndex_], bt->writeIndex_ - bt->readIndex_);
if(nwriten == -1)
{
if(errno != EWOULDBLOCK)
ERR_EXIT("write fd error");
return -1;
}
else
{
bt->readIndex_ += nwriten;
if(bt->readIndex_ == bt->writeIndex_)
{
bt->readIndex_ = bt->writeIndex_ = 0;
}
return nwriten;
}
}

 

Buffer的实现完毕。

 

下文开始编写回射服务器的客户端。

Linux非阻塞IO(三)非阻塞IO中缓冲区Buffer的实现的更多相关文章

  1. {python之IO多路复用} IO模型介绍 阻塞IO(blocking IO) 非阻塞IO(non-blocking IO) 多路复用IO(IO multiplexing) 异步IO(Asynchronous I/O) IO模型比较分析 selectors模块

    python之IO多路复用 阅读目录 一 IO模型介绍 二 阻塞IO(blocking IO) 三 非阻塞IO(non-blocking IO) 四 多路复用IO(IO multiplexing) 五 ...

  2. Java-五种线程池,四种拒绝策略,三种阻塞队列(转)

    Java-五种线程池,四种拒绝策略,三种阻塞队列 三种阻塞队列:    BlockingQueue<Runnable> workQueue = null;    workQueue = n ...

  3. linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO(转载)

      IO概念 Linux的内核将所有外部设备都可以看做一个文件来操作.那么我们对与外部设备的操作都可以看做对文件进行操作.我们对一个文件的读写,都通过调用内核提供的系统调用:内核给我们返回一个file ...

  4. Linux IO模式-阻塞io、非阻塞io、多路复用io

    一 概念说明 在进行解释之前,首先要说明几个概念: - 用户空间和内核空间 - 进程切换 - 进程的阻塞 - 文件描述符 - 缓存 I/O 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对3 ...

  5. 简述linux同步与异步、阻塞与非阻塞概念以及五种IO模型

    1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分 ...

  6. Linux中同步与异步、阻塞与非阻塞概念以及五种IO模型

    1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分 ...

  7. Linux 网络编程的5种IO模型:阻塞IO与非阻塞IO

    背景 整理之前学习socket编程的时候复习到了多路复用,搜索了有关资料,了解到多路复用也有局限性,本着打破砂锅问到底的精神,最终找到了关于IO模型的知识点. 在<Unix网络编程>一书中 ...

  8. Linux IO 同步/异步 阻塞/非阻塞

    同步IO:导致请求进程阻塞,直到IO操作完成: 是内核通知我们何时进行启动IO操作,而实际的IO操作需要当前进程本身阻塞完成: 包括:阻塞式IO模型,非阻塞式IO模型,IO复用模型,信号驱动式IO模型 ...

  9. 网络IO模型:同步IO和异步IO,阻塞IO和非阻塞IO

    同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问题其实不同的人给出 ...

随机推荐

  1. 在AppCode中的razor调用HtmlHelper方法和UrlHelper方法

    原文发布时间为:2011-05-17 -- 来源于本人的百度文章 [由搬家工具导入] 可以写一个帮助类,如下 using System.Web.WebPages;using System.Web.Mv ...

  2. HDU 4649 Professor Tian (概率DP)

    Professor Tian Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)To ...

  3. C++中的 Round(),floor(),ceil()

     2.1             2.6               -2.1               -2.6floor : 不大于自变量的最大整数             2          ...

  4. .h 和 .cpp 切换快捷键设置(转)

    原文转自 https://blog.csdn.net/t163361/article/details/51859274 打开VS后依次选择如下 工具-> 选项-> 环境-> 键盘-& ...

  5. Linux用户态定时器用法以及犯错总结【转】

    转自:http://blog.csdn.net/csdn_logo/article/details/48525703 版权声明:本文为博主原创文章,欢迎转载,转载请注明出处,多谢合作. 采样的时候要用 ...

  6. POCO库中文编程参考指南(3)Poco::Net::Socket

    POCO库中文编程参考指南(3)Poco::Net::Socket 作者:柳大·Poechant 博客:Blog.CSDN.net/Poechant 邮箱:zhongchao.ustc#gmail.c ...

  7. java1.7集合源码阅读:ArrayList

    ArrayList是jdk1.2开始新增的List实现,首先看看类定义: public class ArrayList<E> extends AbstractList<E> i ...

  8. 使用百度地图JavaScript实现驾车/公交/步行导航功能

    <html> <head> <meta http-equiv="Content-Type" content="text/html; char ...

  9. J.U.C并发框架源码阅读(十五)CopyOnWriteArrayList

    基于版本jdk1.7.0_80 java.util.concurrent.CopyOnWriteArrayList 代码如下 /* * Copyright (c) 2003, 2011, Oracle ...

  10. HDU 2955 【01背包+小数概率】

    Robberies Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Sub ...