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服务器端经典 ...
随机推荐
- C#和C实现通过CRC-16 (Modbus)获取CRC值并校验数据(代码)
文章首发于浩瀚先森博客 CRC的全称为Cyclic Redundancy Check,中文名称为循环冗余校验.它是一类重要的线性分组码,编码和解码方法简单,检错和纠错能力强,在通信领域广泛地用于实现差 ...
- 如何在个人博客引擎 Hexo 中添加 Swiftype 搜索组件
在您现在看到的我的博客站点,后台使用的是 Hexo 作为博客引擎,但是默认集成的搜索组件是进行 form 提交到 Google 进行搜索的,为了更好地体验,本文介绍如何在 Hexo 博客中集成 Swi ...
- 51Nod--1015 水仙花数
51Nod: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1015 1015 水仙花数 基准时间限制:1 秒 空间 ...
- 重新注册IIS
出现问题的原因是先装了.NET4.0,再装IIS造成 处理方法:管理员权限执行cmd, C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_reg ...
- IE下a标签后面的span元素向右浮动后错位
错误原因span放在了a标签之后 正确写法是放在之前 如下: <li><span>2016-07-29</span><a href="#" ...
- HCTF时PHP WAF然有RLFI漏洞
tips:from菜鸡队长 这次去打HCTF决赛,用了这个自己写的WAF,web基本上没被打,被打的漏洞是文件包含漏洞,这个功能在本人这个waf里确实很是捉急,由于只是简单检测了..和php[35]{ ...
- 【CityHunter】Unity3D设计AR探索模式
为了增加游戏的乐趣性,我对项目进行了Unity3D的引入,经过一番折腾,终于做出了一个基本的AR探索模式的基本雏形. 途中的小方块就是虚拟物体,因为是静态图片,所以也不能看出什么来,只能文字形容一下: ...
- <<< Tomcat运行提示The server does not support version 3.0
导入了一个项目,运行Tomcat出现此错误大致由于当前导入项目服务器不支持J2ee版本 原因是导入项目的Tomcat版本是6.0,Tomcat 6.0仅支持到Servlet 2.5,而此时项目是3.0 ...
- CSS3中的动画功能(二)
上一篇文章讲解了css3动画中的一个即transitions,那么今天来说说另外一个animations.和transitions不同的是animations可以定义多个关键帧以及每个关键帧中元素的属 ...
- Python之路【第十八篇】Django小项目简单BBS论坛部分内容知识点
开发一个简单的BBS论坛 项目需求: 整体参考“抽屉新热榜” + “虎嗅网” 实现不同论坛版块 帖子列表展示 帖子评论数.点赞数展示 在线用户展示 允许登录用户发贴.评论.点赞 允许上传文件 帖子可被 ...