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服务器端经典 ...
随机推荐
- 使用jQuery加载script脚本
原文链接: Loading Scripts with jQuery JavaScript loaders加载器简单强大而又非常有用.我在博客上介绍过其中一些,例如 curljs 和 LABjs ,也 ...
- WPF之Binding
Binding就是将数据源和目标联系起来,一般来说可以是将逻辑层对象和UI层的控件对象相关联. 有连接就有通道,就可以在通道上建立相应的验证等关卡来验证数据有效性,或是其它处理工作:同时它也支持对数据 ...
- Mongodb学习笔记五(C#操作mongodb)
mongodb c# driver(驱动)介绍 目前基于C#的mongodb驱动有两种,分别是官方驱动(下载地址)和samus驱动(下载地址). 本次我们只演示官方驱动的使用方法. 官方驱动文档查看 ...
- 解决Centos/Redhat,命令不存在
[root@26 ~]# lsb_release #不存在-bash: lsb_release: command not found [root@26 ~] ...
- iOS开发小技巧--iOS程序进入后台运行的实现
iOS程序进入后台运行的实现 视频中看到老师用的iOS7,代码中有开启timer,无限请求数据的功能,但是切换到后台,代码就不打印了 自己用的iOS9,进入后台还是可以打印的,再次进入前台也可以正常运 ...
- 如何在Mac OS X上安装 Ruby运行环境
对于新入门的开发者,如何安装 Ruby和Ruby Gems 的运行环境可能会是个问题,本页主要介绍如何用一条靠谱的路子快速安装 Ruby 开发环境.此安装方法同样适用于产品环境! 系统需求 首先确定操 ...
- ORB-SLAM(四)追踪
最近在读ORB-SLAM的代码,虽然代码注释算比较多了,但各种类和变量互相引用,看起来有点痛苦.索性总结了一下Tracking部分的代码结构,希望能抓住主要思路,不掉坑里. 追踪 追踪部分的主要思路是 ...
- iOS获取本机IP地址
#import <ifaddrs.h> #import <arpa/inet.h> // Get IP Address - (NSString *)getIPAddress { ...
- BUAA_OVERWATCH第一次行动前战略部署
这太IMBA了! 需求调研问卷的反馈 #define A 调查问卷 A设计背景 随着各种新兴手游的兴起,以及各大直播间内Lying Man的火热,以及各种娱乐方式的发展,传统桌游很好地移植到app上的 ...
- 【Phylab2.0】Alpha版本项目展示
团队成员 冯炜韬(PM)http://www.cnblogs.com/toka 岳桐宇(后端)http://www.cnblogs.com/mycraftmw 杨子琛(测试&LaTeX)htt ...