基于epoll的网络服务端模型

#include <stdio.h>
#include <iostream>  //std
#include <string.h>
#include <errno.h>  //perror 打印一些错误信息
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <poll.h> //poll相关实现
#include <sys/epoll.h> //epoll相关实现
#include <vector>
#include <fcntl.h>
#include <pthread.h>
#define IP_ADDR "10.234.19.202"
#define TCP_SERVER_PORT 11000
#define MAX_CLIENT_NUM 3
#define INVALID_SOCKET -1
#define RECV_BUF_SIZE 1024
#define MAX_EVENT_SIZE 1024
#define INVALID_FD -1
#define SERVERSOCEKTNONBLOCK
int main(int argc, char *argv[])
{

    std::cout << "Chat server started!"<< std::endl;
	int ret = 0;
    
	int serverSocketFd = 0;
	serverSocketFd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
	if (serverSocketFd == INVALID_SOCKET)
	{
		std::cout << "creat socket failed!"  << std::endl;
		return -1;
	}

	sockaddr_in local_addr;
	sockaddr_in remote_addr;

	memset(&local_addr, 0x0, sizeof(sockaddr_in));
	memset(&remote_addr, 0x0, sizeof(sockaddr_in));

	local_addr.sin_addr.s_addr = inet_addr(IP_ADDR);
	local_addr.sin_family = AF_INET;
	local_addr.sin_port = htons(TCP_SERVER_PORT);

	int addrlen_ = sizeof(struct sockaddr_in);
	//绑定套接字描述符和指定的ip 端口
	ret = bind(serverSocketFd, (sockaddr*)&local_addr, addrlen_);
	perror("bind");
	if ( ret == -1)
	{
		std::cout << "bind socket and addr failed !" << std::endl;
		close(serverSocketFd);
		return ret;
	}
    //开启监听
	if (-1 == listen(serverSocketFd, MAX_CLIENT_NUM))
	{
		std::cout<<"listen socket failed !"<<std::endl;
        perror("listen");
		close(serverSocketFd);
		// WSACleanup();
		return -1;
	}
	perror("listen");
    
    int epoll_fd = 0 ;
    struct epoll_event evn = {0}; 
    struct epoll_event event[MAX_EVENT_SIZE] = {0};
    epoll_fd = epoll_create(10);
    if(epoll_fd == -1)
    {
        perror("epoll_creat");
        return -1;
    }
    evn.events = EPOLLIN;
//  这里不给这个消息会怎样
    evn.data.fd = serverSocketFd;
    if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD ,serverSocketFd, &evn) == -1 )
    {
        perror("epoll_ctl");
        return -1;
    }

    int n;

    /*开始准备接收消息*/
    while(true)
    {
        /* 第一个是待检测得fd事件,第二个是fd结构体数组得长度,1000是检测超时时间,单位是毫秒*/
        //n = poll(&fds[0],fds.size(),1000);
        n = epoll_wait(epoll_fd,event,MAX_EVENT_SIZE,2000);
        if( n < 0 )
        {   
            /*信号被中断*/
            if(errno == EINTR)
            {
                continue;
            }
            std::cout<<"zzz"<<std::endl;
            break;
        }
        
        else if (n == 0)
        {
            /*超时继续*/
            continue;
        }
        /*如果前面得判断都走过了,说明有事件触发*/
        for(size_t i = 0 ; i < n ; i++)
        {
                if(event[i].events == EPOLLIN )
                {
                    std::cout<<"检测到可读事件, fd = "<<event[i].data.fd<<std::endl;

                    if(event[i].data.fd == serverSocketFd)
                    {
                        std::cout<<"***新的连接请求!***"<<std::endl;
                        //监听socket,接收新连接
                        struct sockaddr_in clientaddr;
                        socklen_t clientaddrlen = sizeof(clientaddr);
                        /*接收客户端的连接并加入到fds合集中*/
                        int clientfd = accept(serverSocketFd,(struct sockaddr *)&clientaddr,&clientaddrlen);
                        if(clientfd != -1)
                        {
                            /*将接收的clientfd设置为非阻塞的*/
                            int oldsocketFlag = fcntl(clientfd,F_GETFL,0);
                            int newsocketFalg = oldsocketFlag | O_NONBLOCK;
                            if( fcntl(clientfd , F_SETFL, newsocketFalg) == -1)
                            {
                                close(clientfd);
                                std::cout<<"set clientfd to nonblock error"<<std::endl;
                            }
                            else
                            {
                                std::cout<<"accpet success!"<<std::endl;
                                //注册clientfd
                                //struct epoll_event client_event;
                                // client_event.events = EPOLLIN;
                                // client_event.data.fd = clientfd;
                                evn.events = EPOLLIN;
                                evn.data.fd = clientfd;
                                if(epoll_ctl(epoll_fd,EPOLL_CTL_ADD,clientfd,&evn) == -1)
                                {
                                    std::cout<<"zzz"<<std::endl;
                                    perror("epoll_ctl");
                                }
                            }
                        }
                        else
                        { 
                            std::cout<<"error ,clientfd = "<<clientfd<<"!"<<std::endl;
                        }
                    }
                    else
                    {
                        std::cout<<"***新的客户端消息!***"<<std::endl;
                        char buf[RECV_BUF_SIZE] = {0};
                        int tempsize = recv(event[i].data.fd,buf,RECV_BUF_SIZE,0);
                        /*如果读取小于等于0*/
                        if( tempsize <= 0)
                        {
                            if(errno != EINTR && errno!= EWOULDBLOCK)
                            {
                                /*出错或者对端关闭了连接,关闭对应的clientfd,并从epollfd中清除*/
                                if( epoll_ctl(epoll_fd,EPOLL_CTL_DEL,event[i].data.fd,NULL) == -1)
                                {
                                    perror("epoll_ctl");
                                    std::cout<<"jjj"<<std::endl;
                                }
                                close(event[i].data.fd);
                            }
                        }
                        else
                        {
                            std::cout<<"Recv buf from client:"<<buf<<std::endl;
                            std::cout<<"clientfd:"<<event[i].data.fd<<std::endl;
                        }
                    }

                }
                if(event[i].events == EPOLLOUT )
                {
                    std::cout<<"检测到可写事件, fd = "<<event[i].data.fd<<std::endl;
                }
                if(event[i].events == EPOLLERR )
                {
                    //To do异常处理
                    std::cout<<"detect EPOLLERR events"<<std::endl;
                }
         }
    }
    std::cout<<"exit normal"<<std::endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值