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服务器端经典 ...
随机推荐
- 微信小程序之数据绑定(五)
[未经作者本人允许,请勿以任何形式转载] 前几篇讲述微信小程序开发工具使用.生命周期和事件. 本次讲述微信小程序数据和视图绑定 >>>数据视图绑定 做前端开发的同学,尤其是WEB前端 ...
- .net ServiceStack.Redis 性能调优
最近在debug生产环境的问题时,发现了ServiceStack 4.0.60版本RedisClient存在一个非常严重的性能问题.在高并发下,PooledRedisClientManager.Get ...
- 谈谈计算机上的那些存储器-Memory Hierarchy
文章首发于浩瀚先森博客http://www.guohao1206.com/2016/12/07/1248.html 说到计算机上的存储器,很多人第一反应是硬盘,然后是内存. 其实在计算机上除了硬盘和内 ...
- 进程间通信(linux)(转)
原帖发表在IBM的developerworks网站上,是一个系列的文章,作者郑彦兴,通过讲解和例子演示了Linux中几种IPC的使用方式,我觉得很好,在这里做一个保留,能看完的话Linux IPC的基 ...
- 【USACO 2.4】The Tamworth Two
题意:C代表cows,F代表farmer,一开始都向北,每分钟前进1步,如果前方不能走,则这分钟顺时针转90°,问多少步能相遇,或者是否不可能相遇,10*10的地图. 题解:dfs,记录状态,C和F的 ...
- BZOJ 3289: Mato的文件管理
3289: Mato的文件管理 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 2368 Solved: 971[Submit][Status][Di ...
- Python Day10
进程 在python中multiprocess模块提供了Process类,实现进程相关的功能.但是,由于它是基于fork机制的,因此不被windows平台支持.想要在windows中运行,必须使用if ...
- virtual和abstract
virtual和abstract都是用来修饰父类的,通过覆盖父类的定义,让子类重新定义. 共同点:如果用来修饰方法,前面必须添加public,要不然就会出现编译错误:虚拟方法或抽象方法是不能私有的. ...
- 学习.Net的经典网站
学习.Net的经典网站 收藏 还不错推荐给大家 原文-- 名称:快速入门 地址:http://chs.gotdotnet.com/quickstart/ 描述:本站点是微软.NET技术的快速入门网站, ...
- foreach statement cannot operate on variables of type 'System.Web.UI.WebControls.Table' because 'System.Web.UI.WebControls.Table' does not contain a public definition for 'GetEnumerator'
错误:foreach statement cannot operate on variables of type 'System.Web.UI.WebControls.Table' because ' ...