c/c++ 使用epoll

来源:互联网 发布:java countdownlatch 编辑:程序博客网 时间:2024/06/17 00:04

epolltest.cpp :
#include <stdio.h>  
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#define MAX_EPOLL_FD_NUM 20000
#define SEND_BUFFER_LEN 1024
#define RECV_BUFFER_LEN 1024
int nb_socket(int domain, int type, int protocol)
{
int sfd = socket(domain, type, protocol), flags = 1;
if (sfd == -1)
return -1;
if(ioctl(sfd, FIONBIO, &flags) &&
((flags = fcntl(sfd, F_GETFL, 0)) < 0 ||
fcntl(sfd, F_SETFL, flags | O_NONBLOCK) < 0))
{
close(sfd);
return -1;
}
return sfd;
}

int main()
{
int epollfd;
int triggered;
int i;
struct epoll_event *events;
struct epoll_event *cevents;
struct epoll_event ev;
unsigned short port = 8008;
struct sockaddr_in addr;
int listenfd, flags = 1;
struct linger ling = {0, 0};
int socks;
time_t now;
char recvbuffer[1024];
int bytes;
unsigned int pkgs;
printf("程序开始执行....创建侦听套接字../n");
if ((listenfd = nb_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
{
printf("失败。。。。呜呜..!");
return 3;
}
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags));
setsockopt(listenfd, SOL_SOCKET, SO_KEEPALIVE, &flags, sizeof(flags));
setsockopt(listenfd, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling));
printf("侦听套接字ID:%d/n",listenfd);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(listenfd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
{
close(listenfd);
return 4;
}
listen(listenfd, 1024);
printf("准备创建EPoll端口...../n");
if((epollfd = epoll_create(MAX_EPOLL_FD_NUM)) < 0)
{
perror("epoll_create");
close(listenfd);
return -1;
}
printf("EPoll端口创建完成...端口号:%d/n",epollfd);
events = (struct epoll_event *)malloc(MAX_EPOLL_FD_NUM * sizeof(struct epoll_event));
printf("将侦听套接字绑定到EPoll端口..../n");
ev.data.fd = listenfd;
ev.events = EPOLLIN | EPOLLERR | EPOLLHUP;
if(epoll_ctl(epollfd, EPOLL_CTL_ADD, listenfd, &ev) < 0)
{
printf("epoll set insertion error: listen socket fd=%d/n", listenfd);
free(events);
close(epollfd);
close(listenfd);
return 5;
}
printf("侦听套接字绑定到EPoll端口完成...进入事件触发等待/n");
socks = 1;

for(int k = 0 ; k < 100; k ++)
{
triggered = epoll_wait(epollfd, events, MAX_EPOLL_FD_NUM, -1);
printf("事件数:%d/n",triggered);
for(i=0; i<triggered; i++)
{
cevents = events + i;
if(cevents->events & (EPOLLERR | EPOLLHUP))
{
printf("POLLERR | POLLHUP fd = %d/r/n", cevents->data.fd);
epoll_ctl(epollfd, EPOLL_CTL_DEL, cevents->data.fd, NULL);
close(cevents->data.fd);
socks--;
continue ;
}
if(cevents->events & EPOLLIN)
{
if(cevents->data.fd == listenfd)
{
struct sockaddr_in addr;
int len;
int sfd;
len = sizeof(addr);
if((sfd = accept(listenfd, (struct sockaddr*)&addr, (socklen_t*)&len)) == -1)
{
perror("accept");
continue;
}
ev.data.fd = sfd;
ev.events = EPOLLIN | EPOLLERR | EPOLLHUP;
epoll_ctl(epollfd, EPOLL_CTL_ADD, sfd, &ev);
socks++;
printf("accpet a connection %s:%d/r/n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
continue;
}
bytes = read(cevents->data.fd, recvbuffer, sizeof(recvbuffer));
if(bytes > 0)
{
printf("套接字:%d,收到字符:%s/t对它注册发送事件./n",cevents->data.fd,recvbuffer);
ev.data.fd = cevents->data.fd;
ev.events = EPOLLOUT;
if(epoll_ctl(epollfd, EPOLL_CTL_MOD, cevents->data.fd, &ev) == -1)
{
perror("对方有数据到来时,这边添加发送事件出错../n");
printf("对套接字:%d,注册发送事件失败.../n",cevents->data.fd);
continue ;
}
}
else
{
printf("套接字:%d,被关闭,注销事件。/n",cevents->data.fd);
ev.data.fd = cevents->data.fd;
ev.events = EPOLLOUT|EPOLLIN|EPOLLERR|EPOLLHUP;
if(epoll_ctl(epollfd, EPOLL_CTL_DEL, cevents->data.fd, &ev) == -1)
{
perror("对方关闭时,这边注销事件出错../n");
printf("对套接字:%d,注销所有事件失败.../n",cevents->data.fd);
close(cevents->data.fd);
continue ;
}
printf("关闭该套接字..");
close(cevents->data.fd);
}
}
if(cevents->events & EPOLLOUT)
{
printf("套接字:%d,有发送事件...现在将该套接字发送事件删除。/n",cevents->data.fd);

send(cevents->data.fd,recvbuffer,bytes,0);
ev.data.fd = cevents->data.fd;
ev.events = EPOLLIN|EPOLLERR|EPOLLHUP;
if(epoll_ctl(epollfd, EPOLL_CTL_MOD, cevents->data.fd, &ev) == -1)
{
perror("可以对套接字发送数据时,这边删除发送事件出错../n");
printf("对套接字:%d,注册发送事件失败.../n",cevents->data.fd);
continue ;
}
}
}
}
return 0;
}
makefile :

#------------------------------------------------------------------------------
# 路径
#------------------------------------------------------------------------------
# include
INC_BOOST = -I/usr/local/include/boost-1_32
INC_POLLER = -I./include
INC_SYS = -I/usr/include
#------------------------------------------------------------------------------
# lib
LIB_BOOST = -L/usr/local/lib -lboost_thread-gcc-mt -lboost_date_time-gcc-mt
LIB_LOG4CPLUS = -L/usr/local/lib -llog4cplus
#------------------------------------------------------------------------------
# 开发环境的定义
C_FLAGS = -g -Wall -pthread -ftemplate-depth-20 -DDEBUG #-DUSE_LOG4CPLUS
LD_FLAGS =
CC = gcc
CXX = g++
RANLIB = ranlib
AR = ar
INC = $(INC_POLLER) #$(INC_BOOST)
LIB = $(LIB_LOG4CPLUS) #$(LIB_BOOST)

BINNAME = epolltest
SRCS = $(wildcard *.cpp)
OBJS = $(patsubst %.cpp,%.o,$(SRCS))
all:$(BINNAME)
$(BINNAME):$(OBJS)
$(CXX) $(C_FLAGS) -o $(BINNAME) *.o
%.o:%.cpp
$(CXX) $(C_FLAGS)$(INC) $(INC_SYS) -o $@ -c $<
clean:
rm -fr *.o $(BINNAME)

0 0
原创粉丝点击