epoll示例
#include <iostream>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h> using namespace std; #define MAXLINE 5
#define OPEN_MAX 100
#define LISTENQ 20
#define SERV_PORT 5000
#define INFTIM 1000 void setnonblocking(int sock)
{
int opts;
opts=fcntl(sock,F_GETFL);
if(opts<)
{
perror("fcntl(sock,GETFL)");
return;
}
opts = opts|O_NONBLOCK; if(fcntl(sock,F_SETFL,opts)<)
{
perror("fcntl(sock,SETFL,opts)");
return;
}
} void CloseAndDisable(int sockid, epoll_event ee)
{
close(sockid);
ee.data.fd = -;
} ssize_t socket_send(int sockfd, const char* buffer, size_t buflen)
{
ssize_t tmp;
size_t total = buflen;
const char *p = buffer; while()
{
tmp = send(sockfd, p, total, );
if(tmp < )
{
if(errno == EINTR)
return -; if(errno == EAGAIN)
{
usleep();
continue;
}
return -;
} if((size_t)tmp == total)
return buflen;
total -= tmp;
p += tmp;
}
return tmp;
}
int main()
{
int i, maxi, listenfd, connfd, sockfd,epfd,nfds, portnumber;
char line[MAXLINE*];
socklen_t clilen;
portnumber = ; struct epoll_event ev,events[];
epfd=epoll_create(); struct sockaddr_in clientaddr;
struct sockaddr_in serveraddr;
listenfd = socket(AF_INET, SOCK_STREAM, ); memset(&serveraddr, , sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port=htons(portnumber); bind(listenfd,(sockaddr *)&serveraddr, sizeof(serveraddr));
listen(listenfd, LISTENQ); ev.data.fd=listenfd;
ev.events=EPOLLIN|EPOLLET; epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev); maxi = ; int bOut = ;
for ( ; ; )
{
if (bOut == )
break;
nfds=epoll_wait(epfd,events,,-);
//printf("wait %d returns\n",nfds);
for(i=;i<nfds;++i)
{
if(events[i].data.fd==listenfd)//如果新监测到一个SOCKET用户连接到了绑定的SOCKET端口
{
connfd = accept(listenfd,(sockaddr *)&clientaddr, &clilen);
if(connfd<){
perror("connfd<0");
return ();
} char *str = inet_ntoa(clientaddr.sin_addr);
cout << "accapt a connection from " << str << endl;
setnonblocking(connfd);
ev.data.fd=connfd;
ev.events=EPOLLIN | EPOLLET;
//注册ev
epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);
}
else if(events[i].events & EPOLLIN)
{
cout << "EPOLLIN" << endl;
if ( (sockfd = events[i].data.fd) < )
continue; cout << "START READ" << endl;
char * head = line;
int recvNum = ;
int count = ;
bool bReadOk = false;
while()
{
recvNum = recv(sockfd, head+count, MAXLINE-, );
if(recvNum < )
{
if(errno == EAGAIN)
{//已没数据 不阻塞等待
bReadOk = true;
break;
}
else if (errno == ECONNRESET)
{
CloseAndDisable(sockfd, events[i]);
cout << "counterpart send out RST\n";
break;
}
else if (errno == EINTR)
{//有数据但未读到断了,所以要接着读
continue;
}
else
{
CloseAndDisable(sockfd, events[i]);
cout << "unrecovable error\n";
break;
}
}
else if( recvNum == )
{
CloseAndDisable(sockfd, events[i]);
cout << "counterpart has shut off\n";
break;
} count += recvNum;
if ( recvNum == MAXLINE-)
{
cout << "sleeping..."<<endl;
sleep();
cout << "recvNum == MAXLINE-1\n"<<endl;
continue;
}
else // 0 < recvNum < MAXLINE-1
{
cout << "0 < recvNum < MAXLINE-1"<<endl;
bReadOk = true;
break; // 退出while(1),表示已经全部读完数据
} } if (bReadOk == true)
{
line[count] = '\0';
cout << "we have read from the client : " << line;
ev.data.fd=sockfd;
ev.events = EPOLLOUT | EPOLLET;
epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
}
}
else if(events[i].events & EPOLLOUT) // 如果有数据发送
{
cout << "EPOLLOUT" << endl;
const char str[] = "";
//printf("%d\n",sizeof(str));
memcpy(line, str, sizeof(str));
//cout << line << endl;
printf("d %d u %u lu %lu\n",i,i,i);
sockfd = events[i].data.fd;
int bWritten = ;
int writenLen = ;
int count = ;
char * head = line;
bWritten=socket_send(sockfd,head,strlen(head));
if (bWritten == strlen(head))
{
ev.data.fd=sockfd;
ev.events=EPOLLIN | EPOLLET;
epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
}
}
}
}
return ;
}
关于epoll和accept的注意点,参见http://www.ccvita.com/515.html
epoll示例的更多相关文章
- IO多路复用:select、poll、epoll示例
一.IO多路复用 所谓IO多路复用,就是通过一种机制,一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作. Linux支持IO多路复用的系统调用有 ...
- epoll使用详解
目录 epoll介绍 Epoll的优点: 1.支持一个进程打开大数目的socket描述符(FD) 2.IO效率不随FD数目增加而线性下降 3.支持边缘触发模式 4.使用mmap加速内核与用户空间的消息 ...
- 【GoLang】并发小结
006.并发 1 概念 1.1 goroutine是Go并行设计的核心,goroutine的本质是轻量级线程 1.2 golang的runtime实现了对轻量级线程即goroutine的智能调度管理 ...
- 网络IO-阻塞、非阻塞、IO复用、异步
网络socket输入操作分为两个阶段:等待网络数据到达和将到达内核的数据复制到应用进程缓冲区.对这两个阶段不同的处理方式将网络IO分为不同的模型:IO阻塞模型.非阻塞模型.多路复用和异步IO. 一 阻 ...
- 有点长的博客:Redis不是只有get set那么简单
我以前还没接触Redis的时候,听到大数据组的小伙伴在讨论Redis,觉得这东西好高端,要是哪天我们组也可以使用下Redis就好了,好长一段时间后,我们项目中终于引入了Redis这个技术,我用了几下, ...
- 一文弄懂-BIO,NIO,AIO
目录 一文弄懂-BIO,NIO,AIO 1. BIO: 同步阻塞IO模型 2. NIO: 同步非阻塞IO模型(多路复用) 3.Epoll函数详解 4.Redis线程模型 5. AIO: 异步非阻塞IO ...
- Redis不是只有get set那么简单
我以前还没接触Redis的时候,听到大数据组的小伙伴在讨论Redis,觉得这东西好高端,要是哪天我们组也可以使用下Redis就好了,好长一段时间后,我们项目中终于引入了Redis这个技术,我用了几下, ...
- 通过完整示例来理解如何使用 epoll
网络服务器通常使用一个独立的进程或线程来实现每个连接.由于高性能应用程序需要同时处理大量的客户端,这种方法就不太好用了,因为资源占用和上下文切换时间等因素影响了同时处理大量客户端的能力.另一种方法是在 ...
- epoll经典代码示例
1. epoll原理 原理性的知识不再另做说明,我在这里附上收藏整理的两篇经典文章: select与epoll的本质关系. select.poll.epoll之间的区别. 2. epoll服务器端经典 ...
随机推荐
- 微信小程序入门正确姿势(一)
[未经作者本人同意,请勿以任何形式转载] >>>前言 这是 [认真学编程] 系列的 第4篇 文章(微信小程序入门系列),欢迎点赞分享.写留言,这些都是对我最好的支持. 本系列适合有一 ...
- 通过COOKIE欺骗登录网站后台
1.今天闲着没事看了看关于XSS(跨站脚本攻击)和CSRF(跨站请求伪造)的知识,xss表示Cross Site Scripting(跨站脚本攻击),它与SQL注入攻击类似,SQL注入攻击中以SQL语 ...
- Ubuntu 14 設定 遠端連線,讓別台電腦可以連線進來
Ubuntu 14 需 disable 加密,方可 遠端連線 此台電腦 xxx@xxx-ThinkPad-T460p:~$ gsettings set org.gnome.Vino require-e ...
- outlook 2016 for windows 每次刷新发送接收邮件会弹出登陆界面
Q: outlook2016 for windows 每次刷新发送接收邮件会弹出登陆界面,office365 ProPlus 都是正常激活了,Word 和Excel都不存在此类问题 A: 排除用户的o ...
- 【USACO 2.4】Cow Tours (最短路)
题意:给你n(最多150)个点的坐标,给出邻接矩阵,并且整个图至少两个联通块,现在让你连接一条边,使得所有可联通的两点的最短距离的最大值最小. 题解:先dfs染色,再用floyd跑出原图的直径O($n ...
- 更新/替换系统 hosts,轻松访问国外站点
更新 hosts 下面介绍的操作均可能覆盖现有 hosts ,进行操作前请先确认是否需要备份. 推荐使用本项目的 Host Tools 来自动化 备份/配置 工作. 若更新 hosts 未立即生效,请 ...
- 编译CM13源码添加来去电归属地 SudaMod开源项目,查看commit提交记录
这个问题纠结了很多时间,感谢苏打先森@Sudamod的开源项目. 大家知道CM13是没有来去点归属地的,就算有那也是google,对于中国人不适用,所以这里把方法贡献出来. 1.与通话有关的app D ...
- Windows简单几步实现系统自动关机设置
首先按win+R快捷键打开“运行输入框”,也可以在电脑左下角打开“运行” 然后输入“Taskschd.msc” 接下来,就会弹出如下“任务计划程序” 点击操作,创建基本任务. 名称”和“描述”随便填一 ...
- 【bzoj3505】 Cqoi2014—数三角形
http://www.lydsy.com/JudgeOnline/problem.php?id=3505 (题目链接) 题意 给定一个n*m的网格,请计算三点都在格点上的三角形共有多少个. Solut ...
- Eclipse Maven3新建web项目
环境: Eclipse Neon JDK1.8 先决条件: 本机下载apache-tomcat-8,解压,在Eclipse->preferences->server里配置安装目录.并在ec ...