unix网络编程 str_cli epoll 非阻塞版本

unix网络编程str_cli使用epoll实现讲了使用epoll配合阻塞io来实现str_cli,这个版本是配合非阻塞io.
可以看到采用非阻塞io以后复杂度大大提升了. 这个版本是在原书select版本基础之上修改而来,可以看出epoll又比select版本复杂了很多,每次都需要调用epoll_ctl三次,效率肯定比select还低.

存在一个问题!!就是epoll_wait对于重定向的stdin,始终阻塞,不晓得什么原因,以后再研究吧!

因为不能重定向stdin所以也不能测试性能,只能说是可以工作.

/* include nonb1 */
#include    "../lib/unp.h"
#include <sys/epoll.h>
//epoll 非阻塞io, 采用了非阻塞io以后性能得到大幅提升,但是复杂度也飞速提升。//确保events有足够的空间,这里足够了
//添加一个事件到队列中,可能会改变数组中的epoll_event数量。
static uint32_t addEvents(struct epoll_event * events,uint32_t nfds,int fd,uint32_t event){int i=0;for(i=0;i<nfds;i++){if(events[i].data.fd==fd){events[i].events|=event;}}if(i==nfds){events[i].data.fd=fd;events[i].events=event;nfds++;}return nfds;
}
#define VOL2
void str_cli(FILE *fp, int sockfd)
{int         val,stdineof=0;ssize_t     n, nwritten;char        to[MAXLINE], fr[MAXLINE];char        *toiptr, *tooptr, *friptr, *froptr;struct epoll_event event;struct epoll_event events[20];int i,efd,nfds;int noevent=0;val = Fcntl(sockfd, F_GETFL, 0);Fcntl(sockfd, F_SETFL, val | O_NONBLOCK);val = Fcntl(STDIN_FILENO, F_GETFL, 0);Fcntl(STDIN_FILENO, F_SETFL, val | O_NONBLOCK);val = Fcntl(STDOUT_FILENO, F_GETFL, 0);Fcntl(STDOUT_FILENO, F_SETFL, val | O_NONBLOCK);toiptr = tooptr = to;   /* initialize buffer pointers */friptr = froptr = fr;stdineof = 0;efd = epoll_create (10);if(efd<0){err_sys("epoll create failed");}event.data.fd=fileno(fp);event.events=EPOLLIN;epoll_ctl(efd,EPOLL_CTL_ADD,fileno(fp),&event);event.data.fd=sockfd;event.events=EPOLLIN;epoll_ctl(efd,EPOLL_CTL_ADD,sockfd,&event);event.data.fd=STDOUT_FILENO;event.events=EPOLLOUT;epoll_ctl(efd,EPOLL_CTL_ADD,STDOUT_FILENO,&event);for ( ; ; ) {event.data.fd = fileno(fp);event.events = 0;//fprintf(stderr, "tooptr=0x%x,toiptr=0x%x,froptr=0x%x,friptr=0x%x \n", tooptr, toiptr, froptr, friptr);if (stdineof == 0 && toiptr < &to[MAXLINE]) //并不能确定在不在里面,多做一次不是坏事{event.events = EPOLLIN;epoll_ctl(efd, EPOLL_CTL_MOD, fileno(fp), &event); //read from stdin}elseepoll_ctl(efd, EPOLL_CTL_MOD, fileno(fp), &event);event.data.fd = sockfd;event.events = 0;if (friptr < &fr[MAXLINE])event.events |= EPOLLIN;            /* read from socket */if (tooptr != toiptr)event.events |= EPOLLOUT;            /* data to write to socket */epoll_ctl(efd, EPOLL_CTL_MOD, sockfd, &event);event.data.fd = STDOUT_FILENO;event.events = 0;if (froptr != friptr) {event.events = EPOLLOUT;epoll_ctl(efd, EPOLL_CTL_MOD, STDOUT_FILENO, &event);    /* data to write to stdout */}else {epoll_ctl(efd, EPOLL_CTL_MOD, STDOUT_FILENO, &event);}nfds = epoll_wait(efd, events, sizeof(events) / sizeof(struct epoll_event), -1);//fprintf(stderr, "nfds return:%d, %d,0x%x,sockfd=%d\n", nfds, events[0].data.fd, events[0].events, sockfd);startloop:for (i = 0; i < nfds; i++) {if (events[i].data.fd == STDIN_FILENO && events[i].events != 0) {events[i].events = 0; //清除处理过的事件if ((n = read(STDIN_FILENO, toiptr, &to[MAXLINE] - toiptr)) < 0) {if (errno != EWOULDBLOCK)err_sys("read error on stdin");} else if (n == 0) {
#ifdef    VOL2fprintf(stderr, "%s: EOF on stdin\n", gf_time());
#endifstdineof = 1;            /* all done with stdin */if (tooptr == toiptr)Shutdown(sockfd, SHUT_WR);/* send FIN */} else {
#ifdef    VOL2fprintf(stderr, "%s: read %d bytes from stdin\n", gf_time(), n);
#endiftoiptr += n;            /* # just read */int ret2=addEvents(events, nfds, sockfd, EPOLLOUT);if(ret2!=nfds){nfds=ret2;goto startloop;}}}if (events[i].data.fd == sockfd && events[i].events != 0) {if (events[i].events & EPOLLIN) {printf("read socket\n");if ((n = read(sockfd, friptr, &fr[MAXLINE] - friptr)) < 0) {printf("read socket error");if (errno != EWOULDBLOCK)err_sys("read error on socket");} else if (n == 0) {
#ifdef    VOL2fprintf(stderr, "%s: EOF on socket\n", gf_time());
#endifif (stdineof)return;        /* normal termination */elseerr_quit("str_cli: server terminated prematurely");} else {
#ifdef    VOL2fprintf(stderr, "%s: read %d bytes from socket\n",gf_time(), n);
#endiffriptr += n;        /* # just read */int ret2 = addEvents(events, nfds, STDOUT_FILENO, EPOLLOUT);/* try and write for next loop */if(ret2!=nfds){nfds=ret2;events[i].events&=~EPOLLIN; //清除已经处理过的in事件goto startloop;}}}if (events[i].events & EPOLLOUT) {if ((n = toiptr - tooptr) > 0) {if ((nwritten = write(sockfd, tooptr, n)) < 0) {if (errno != EWOULDBLOCK)err_sys("write error to socket");} else {
#ifdef    VOL2fprintf(stderr, "%s: wrote %d bytes to socket\n",gf_time(), nwritten);
#endiftooptr += nwritten;    /* # just written */if (tooptr == toiptr) {toiptr = tooptr = to;    /* back to beginning of buffer */if (stdineof)Shutdown(sockfd, SHUT_WR);    /* send FIN */}}}}events[i].events = 0; //清除处理过的事件}if (events[i].data.fd == STDOUT_FILENO) {if ((n = friptr - froptr) > 0) {if ((nwritten = write(STDOUT_FILENO, froptr, n)) < 0) {if (errno != EWOULDBLOCK)err_sys("write error to stdout");} else {
#ifdef    VOL2fprintf(stderr, "%s: wrote %d bytes to stdout\n",gf_time(), nwritten);
#endiffroptr += nwritten;        /* # just written */if (froptr == friptr)froptr = friptr = fr;    /* back to beginning of buffer */}}}}}
}

unix网络编程 str_cli epoll 非阻塞版本相关推荐

  1. 网络编程学习笔记(非阻塞读和写)

    维护两个缓冲区:to容纳从标准输入到服务器的数据,from容纳从服务器到标准输出的数据 toiptr指向从标准输入读入的数据可以存放的下一个字节,tooptr指下一个必须写入到套接口的字节.有(toi ...

  2. 网络编程学习笔记(非阻塞accept)

    修改TCP回射客户程序,在跟服务器建立连接后发送一个RST.这种情况可以如下模拟: 一旦建立连接,设置SO_LINGER选项,把l_onoff标志置为1,l_linger时间置为0.在关闭连接时,TC ...

  3. 网络编程学习笔记(非阻塞connect)

    设置非阻塞,如果返回EINPROGRESS,表示正在建立连接,还没有完成 非阻塞的三个用途: 1.我们可以在三路握手的同时做其它的处理.connect要花一个往返时间完成,而且可以是在任何地主,从几个 ...

  4. linux下网络编程设置非阻塞,UNIX网络编程 非阻塞connect的实现

    一.<UNIX网络编程>-非阻塞connect 在一个TCP套接口被设置为非阻塞之后调用connect,connect会立即返回EINPROGRESS错误,表示连接操作正在进行中,但是仍未 ...

  5. UNIX网络编程学习笔记(代码超详细解析)(持续更新)

    1. 其他函数准备 1. TCP 回射服务器程序: str_echo 函数 #include "unp.h"void str_echo(int sockfd) {ssize_t n ...

  6. UNIX网络编程卷1 回射客户程序 TCP客户程序设计范式

    本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 下面我会介绍同一个使用 TCP 协议的客户端程序的几个不同版本,分别是停等版本.select ...

  7. 网编编程必看书籍:unix网络编程

    unix网络编程被誉为圣经,该书主要讲socket套接字相关,socket API,从底层剖析网络编程.网络编程中需要用到的一些经典函数,多路复用函数,这些都值得去反复学习研究. 目录: 录 Part ...

  8. Unix网络编程---第三次作业

    Unix网络编程---第三次作业 要求: 利用多线程技术实现如下并发网络程序,要求对上课时的实现进行完善,利用线程专用数据TSD实现. 服务端: 服务器等待客户连接,连接成功后显示客户地址,接着接收该 ...

  9. UNIX网络编程.卷1,套接字联网API(第3版)(中文版)(Stevens经典著作,两位顶级网络编程专家应邀执笔修订)...

    UNIX网络编程.卷1,套接字联网API(第3版)(中文版)(Stevens经典著作,两位顶级网络编程专家应邀执笔修订) 基本信息 原书名: Unix Network Programming, Vol ...

最新文章

  1. linux 关闭开机 ftp,解决linux ftp匿名上传、下载开机自启问题
  2. AI:百度飞桨EasyDL多门视频课程,手把手教你如何定制高精度AI模型
  3. JGroups 入门实践(转)
  4. 两个负数相减计算机如何表示,计算机如何表示整数
  5. redis生产环境下部署lua脚本
  6. 极客产品经理学习笔记
  7. java关于异常的面试程序题_Java挑战:最难的十个面试题(附答案)「下」
  8. 后缀自动机(SAM)构造实现过程演示+习题集锦
  9. 深度学习课程笔记(七):模仿学习(imitation learning)
  10. 中国移动国际mCloud如何助力企业乘风破浪?
  11. 解决onenote 错误 0xE000078D
  12. 计算机应用技术视频剪辑,万能的剪辑、合并视频、音频的技术 爱剪辑使用教程...
  13. Python第三课:列表,元组,集合
  14. 手机(局域网)远程连接 windows电脑
  15. ...可变形参的使用
  16. VerilogA学习 - VCO demo 合集
  17. yum 安装mysql 后 which is not functionally dependent on columns in GROUP BY clause; this is incompatibl
  18. Sqlmap参数详解
  19. Java语法(全面解析)
  20. SMB交换机、接入交换机、汇聚交换机、核心交换机

热门文章

  1. Abstract Self-Balancing Binary Search Tree
  2. linux内核相关知识
  3. Docker 的日志相关整理
  4. 《Python Cookbook 3rd》笔记(1.2):拆分任意长可迭代对象后赋值给多个变量
  5. 计算机分php,计算机按照处理数据的形态分类,可以分为什么?
  6. php 配置 gd2,配置PHP对gd库的支持
  7. 安卓布局位置,dp与px的区别
  8. linux opencl(AMD) Example
  9. 扬尼斯定律:程序员的开发效率每6年提高一倍
  10. 一个人幸运的前提,是他有能力改变自己