#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <strings.h>
#include <errno.h>
#include <error.h>
#include <poll.h>
#define LISTENQ 20
#define OPEN_MAX 128
#define TIMEOUT_EPOLL -1
#define MAX_MESSAGE_SIZE 1024
unsigned int current_connect=0;
int epollAccept(int epfd,int servfd,struct sockaddr_in *clientAddr,socklen_t *addrlen);
int epollClient(int epfd,struct epoll_event *events);
int main(int argc,char *argv[]){
int i=0;
if(argc!=2){
printf("%s <port>\n",argv[0]);
exit(0);
}
/* 1.创建套接字 */
int servfd=socket(AF_INET,SOCK_STREAM,0);
if(servfd == -1){
perror("socket");
exit(0);
}
/* 2.设置套接字地址 */
struct sockaddr_in servAddr,clientAddr;
socklen_t addrlen = sizeof(servAddr);
bzero(&servAddr,addrlen);
bzero(&clientAddr,addrlen);
servAddr.sin_family=AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(atoi(argv[1]));
/* 3.bind地址 */
int err = bind(servfd,(struct sockaddr *)&servAddr,addrlen);
if(err == -1){
perror("bind");
}
/* 4/listen,服务器变为LISTEN状态 */
err = listen(servfd,LISTENQ);
if(err == -1){
perror("listen");
}
/* 5.创建epfd描述符 */
int epfd = epoll_create(1);
/* 6.添加事件 */
struct epoll_event ev;
bzero(&ev,sizeof(ev));
ev.data.fd = servfd;
ev.events = EPOLLIN | EPOLLET;//可读事件(新的连接),边沿触发
err = epoll_ctl(epfd,EPOLL_CTL_ADD,servfd,&ev);
if(err == -1){
perror("epoll_ctrl");
exit(0);
}
/* 7.创建事件 */
struct epoll_event events[OPEN_MAX];
/* 8.等待事件 */
while(1){
int nfd = epoll_wait(epfd,events,current_connect+1,-1);
//printf("nfd = %d\n",nfd);
for(i=0;i<nfd;i++){
/* 如果是servfd可读,即有新的连接,服务器处于SYN_RCVD状态 */
//printf("now is event[%d]\n",i);
if(events[i].data.fd == servfd){
/* 接受连接,服务器状态变为:ESTABLISHED */
epollAccept(epfd,servfd,&clientAddr,&addrlen);
}else if(events[i].events&EPOLLIN){//如果是可读事件
epollClient(epfd,&events[i]);
}else{
printf("fd = %d\n",events[i].data.fd);
printf("没有理由运行到这里啊!\n");
}
}
}
return 0;
}
/**
* @function:接收一个新的连接,加入epfd监听的队列
*
*/
int epollAccept(int epfd,int servfd,struct sockaddr_in *clientAddr,socklen_t *addrlen){
struct epoll_event ev;
int clientfd = accept(servfd,(struct sockaddr *)clientAddr,addrlen);
if(clientfd == -1){
perror("accept");
}else{
char *str = inet_ntoa(clientAddr->sin_addr);
printf("got a new connection:%s ,fd = %d!\n",str,clientfd);
current_connect+=1;
ev.data.fd = clientfd;
ev.events = EPOLLIN | EPOLLET;
epoll_ctl(epfd,EPOLL_CTL_ADD,clientfd,&ev);
}
return clientfd;
}
/**
*@function:处理用户的数据
*
*/
int epollClient(int epfd,struct epoll_event *events){
struct epoll_event ev;
char buf[MAX_MESSAGE_SIZE];
int count=0;
int sockfd = -1;
if( (sockfd = events->data.fd) < 0)
return -1;
bzero(buf,MAX_MESSAGE_SIZE);
if ( (count = read(sockfd, buf, MAX_MESSAGE_SIZE)) < 0) {
/* 1.对端发送FIN后,还向这个套接字写会受到RST */
if (errno == ECONNRESET) {
epoll_ctl(epfd,EPOLL_CTL_DEL,sockfd,&ev);
close(sockfd);
current_connect--;
events->data.fd = -1;
}
perror("read sockfd");
return -2;
}
/* 2.对方发送了FIN,服务器读会返回0,应答后处于CLOSE_WAIT状态 */
else if (count == 0){
epoll_ctl(epfd,EPOLL_CTL_DEL,sockfd,&ev);
close(sockfd);
current_connect--;
events->data.fd = -1;
return -3;
}
/* 3.正常读数据 */
buf[count]=0; //添加结束符
printf("recv :%s",buf); //打印接收的数据
return 0;
}
epoll---简单服务器
猜你喜欢
转载自blog.csdn.net/qq_36337149/article/details/81488953
今日推荐
周排行