Linux非阻塞IO(三)非阻塞IO中缓冲区Buffer的实现
本文我们来实现回射服务器的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的实现的更多相关文章
- {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) 五 ...
- Java-五种线程池,四种拒绝策略,三种阻塞队列(转)
Java-五种线程池,四种拒绝策略,三种阻塞队列 三种阻塞队列: BlockingQueue<Runnable> workQueue = null; workQueue = n ...
- linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO(转载)
IO概念 Linux的内核将所有外部设备都可以看做一个文件来操作.那么我们对与外部设备的操作都可以看做对文件进行操作.我们对一个文件的读写,都通过调用内核提供的系统调用:内核给我们返回一个file ...
- Linux IO模式-阻塞io、非阻塞io、多路复用io
一 概念说明 在进行解释之前,首先要说明几个概念: - 用户空间和内核空间 - 进程切换 - 进程的阻塞 - 文件描述符 - 缓存 I/O 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对3 ...
- 简述linux同步与异步、阻塞与非阻塞概念以及五种IO模型
1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分 ...
- Linux中同步与异步、阻塞与非阻塞概念以及五种IO模型
1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分 ...
- Linux 网络编程的5种IO模型:阻塞IO与非阻塞IO
背景 整理之前学习socket编程的时候复习到了多路复用,搜索了有关资料,了解到多路复用也有局限性,本着打破砂锅问到底的精神,最终找到了关于IO模型的知识点. 在<Unix网络编程>一书中 ...
- Linux IO 同步/异步 阻塞/非阻塞
同步IO:导致请求进程阻塞,直到IO操作完成: 是内核通知我们何时进行启动IO操作,而实际的IO操作需要当前进程本身阻塞完成: 包括:阻塞式IO模型,非阻塞式IO模型,IO复用模型,信号驱动式IO模型 ...
- 网络IO模型:同步IO和异步IO,阻塞IO和非阻塞IO
同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问题其实不同的人给出 ...
随机推荐
- 51nod 1273 旅行计划——思维题
某个国家有N个城市,编号0 至 N-1,他们之间用N - 1条道路连接,道路是双向行驶的,沿着道路你可以到达任何一个城市.你有一个旅行计划,这个计划是从编号K的城市出发,每天到达一个你没有去过的城市, ...
- [ CodeVS冲杯之路 ] P1044
不充钱,你怎么AC? 题目:http://codevs.cn/problem/1044/ 机房连续断网,搞得现在才能上博客…… 很经典的DP题,把问题转换一下就是分别求最不降序列和最长上升序列 f[i ...
- 战斗机的祈雨仪式(NOIP模拟赛Round 7)
[问题描述] 炎炎夏日,如果没有一场大雨怎么才能尽兴?秋之国的人民准备了一场祈雨仪式.战斗机由于拥有操纵雷电的能力,所以也加入了其中,为此,她进行了一番准备. 战斗机需要给自己的Spear of Lo ...
- 跳石头(NOIP2015) (二分查找)
原题传送门 好久没更了..昨天去学zkw线段树,被zxyer狠狠地D了一顿.. 来补坑.. 这是一道很奇特的题目. 根据题目可以看出这道题有二分题具有的性质.. 不懂二分性质的可以看我以前的博客 传送 ...
- 无线网络发射器选址 (NOIP2014)(真·纯模拟)
原题传送门 好吧,如果说D1T1是纯模拟大水题 D2T1就是纯模拟略水题. 这道题首先我们要看一看数据范围.. 0<=n,m<=128 送分也不带这么送的吧.. 二维前缀和,前缀和,二次循 ...
- C/S模式和BS模式是什么?
C/S是Client/Server,即客户端/服务器:B/S是Browser/Server,即浏览器/服务器的意思. C/S (Client/Server)结构,即大家熟知的客户机和服务器结构.它 ...
- Android BroadcastReceiver使用
1. 介绍 BroadcastReceiver用于接收广播事件(Intent), 是Android四大组件之一 2. 使用 2.1 实现广播接收类 实现一个广播收类继承BroadcastReceiv ...
- 华为上机测试题(Excel表格纵列字母数字转换-java)
PS:这是我刚做的一道题,题目不难,满分60,得分40,大家看看哪里有问题,欢迎提意见,感谢! /* * 题目:Excel表格纵列字母数字转换 * 描述: 在Excel中列的编号为A-Z,AA-AZ, ...
- HTTP GET与POST区别
HTTP定义了与服务器交互的不同方法,最基本的方法是 GET 和 POST. HTTP-GET和HTTP-POST是使用HTTP的标准协议动词,用于编码和传送变量名/变量值对参数,并且使用相关的请求语 ...
- 一个boost底下的线程池
Boost的thread库中目前并没有提供线程池,我在sorceforge上找了一个用boost编写的线程池.该线程池和boost结合的比较好,并且提供了多种任务执行策略,使用也非常简单. 下载地址: ...