#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <errno.h>
#define MAXEVENTS 64
#define PORT 8888
#define BUFFSIZE 1024
#define ADDR "127.0.0.1"
#define LISTEN_SIZE 5
/*绑定端口*/
int makeSocketAndBind(short int port)
{
//init parameters
struct sockaddr_in sAddr;
int sfd = -1;
int r = -1;
//socket
sfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sfd < 0)
{
perror("socket error. ");
return -1;
}
//bind
sAddr.sin_family = AF_INET;
sAddr.sin_port = htons(port);
sAddr.sin_addr.s_addr = inet_addr(ADDR);
r = bind(sfd, (struct sockaddr*)&sAddr, sizeof(sAddr));
if(-1 == r)
{
perror("bind error");
close(sfd);
return -1;
}
return sfd;
}
int main(int argc, char * argv [ ])
{
//初始化变量
int sfd = -1, cfd = -1, efd = -1;
int rtn = -1, count = -1, i = 0, n = -1;
struct epoll_event event, *events = NULL;
char buf[BUFFSIZE];
//设置和绑定套接字
sfd = makeSocketAndBind(PORT);
if(-1 == sfd)
{
perror("makeSocketAndBind() error.");
exit(0);
}
//监听套接字
rtn = listen(sfd, LISTEN_SIZE);
if(-1 == rtn)
{
perror("listen error");
close(sfd);
exit(0);
}
//加入epoll
efd = epoll_create(MAXEVENTS);
if(-1 == efd)
{
perror("epoll_create error");
exit(0);
}
memset(&event, 0, sizeof(event));
event.data.fd = sfd;
event.events = EPOLLIN | EPOLLET;
rtn = epoll_ctl(efd, EPOLL_CTL_ADD, sfd, &event);
if(-1 == rtn)
{
perror("epoll_ctl error");
exit(0);
}
//申请响应事件缓冲区
events = calloc(MAXEVENTS, sizeof(event));
if(NULL == events)
{
perror("calloc error.");
exit(0);
}
puts("go in main loop");
//事件循环
while(1)
{
memset(events, 0, sizeof(events));
count = epoll_wait(efd, events, MAXEVENTS, -1);
//error
if(count < 0)
{
perror("epoll_wait error");
exit(0);
}//time out
else if(0 == count)
{
perror("epoll_wait timeout.");
continue;
}//event handle
else
{
puts("event happened.");
for(i = 0; i < count; ++i)
{
//new connection
if(events[i].data.fd == sfd)
{
puts("New connection.");
if(EPOLLIN & events[i].events)
{
cfd = accept(sfd, NULL, NULL);
if(-1 == cfd)
{
perror("accept error.");
continue;
}
//add new socket
memset(&event, 0, sizeof(event));
event.data.fd = cfd;
event.events = EPOLLIN | EPOLLET;
rtn = epoll_ctl(efd, EPOLL_CTL_ADD, cfd, &event);
if(-1 == rtn)
{
perror("epoll_ctl error");
exit(0);
}
fprintf(stdout, "epoll_ctl add fd[%d]\n", cfd);
}
else if((EPOLLERR & events[i].events) ||
(EPOLLHUP & events[i].events) ||
(!(EPOLLIN & events[i].events)))
{
fprintf(stderr, "Get unexpected events. i=%d, fd=%d, event=%d\n", i, events[i].data.fd, events[i].events);
close(events[i].data.fd);
epoll_ctl(efd, EPOLL_DEL, events[i].data.fd, &event);
exit(0);
}
}//ready to read
else
{
//receive data
if(EPOLLIN & events[i].events)
{
memset(buf, 0, sizeof(buf));
n = read(events[i].data.fd, buf, sizeof(buf) -1 );
if(n < 0)
{
perror("read error.");
close(events[i].data.fd);
epoll_ctl(efd, EPOLL_CTL_DEL, events[i].data.fd, &events[i]); //???
continue;
}
fprintf(stdout, "recv data:%s", buf);
write(events[i].data.fd, buf, n);
}//
else if((EPOLLERR & events[i].events) ||
(EPOLLHUP & events[i].events) ||
(!(EPOLLIN & events[i].events)))
{
fprintf(stderr, "Get unexpected events. i=%d, fd=%d, event=%d\n", i, events[i].data.fd, events[i].events);
close(events[i].data.fd);
epoll_ctl(efd, EPOLL_DEL, events[i].data.fd, &event);
}
}
}
}
}
free(events);
return 0;
}