TCP & EPOLL服务器编程

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <sys/epoll.h>
#include <errno.h>
#include <pthread.h>

#define MAX_EPOLL_SIZE 20
#define MAX_EPOLL_TIMEOUT 500  //ms
#define MAX_BUFF_SIZE 100 //接受包大于100字节时,循环接收
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

int epoll_fd = 0;

int set_fd_nonblocking(int fd)
{
    int opts = fcntl(fd, F_GETFL);
    if(0 > opts) 
    {
        printf("fcntl failed !\n");
        return -1;
    }
    opts = opts | O_NONBLOCK;
    return fcntl(fd, F_SETFL, opts);
}

void do_tcp(int client_fd,struct sockaddr_in addr,char * buff,int len)
{
    printf(" buff is : %s , len = %d\n",buff,len);
}

int init_network()
{
    struct sockaddr_in addr;
    int tmp = 1;
    
    bzero(&addr,sizeof(addr));
    
    int fd = socket(AF_INET,SOCK_STREAM,0);
    if(fd < 0)
    {
        printf("create socket failed !\n");
        return -1;
    }

    if(setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&tmp,sizeof(tmp)))
    {
        printf("setsockopt failed !\n");
        close(fd);
        return -1;
    }

    addr.sin_family = AF_INET;
    addr.sin_port = htons(8888);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);

    if(bind(fd,(struct sockaddr *)&addr,sizeof(addr)) < 0)
    {
        printf("bind failed !\n");
        close(fd);
        return -1;
    }

    if(listen(fd,20) < 0)
    {
        printf("listen failed !\n");
        close(fd);
        return -1;
    }    
    
    if(set_fd_nonblocking(fd) < 0)
    {
        printf("set_fd_nonblocking failed !\n");
        close(fd);
        return -1;
    }
    return fd;

}

int init_epoll()
{
    epoll_fd = epoll_create(MAX_EPOLL_SIZE);
    if(epoll_fd < 0)
    {
        printf("epoll_create failed !\n");
        return -1;
        
    }
    
    return 0;
}

int add_epoll_ctl(int fd)
{
    struct epoll_event event;
    
    memset(&event,0,sizeof(event));
    event.events = EPOLLIN | EPOLLET;
    event.data.fd = fd;
    
    if(epoll_ctl(epoll_fd,EPOLL_CTL_ADD,fd,&event) < 0)
    {
        printf("epoll_ctl EPOLL_CTL_ADD failed !\n");
        return -1;
    }
    
    return 0;
}

int del_epoll_ctl(int fd)
{
    struct epoll_event event;
    
    memset(&event,0,sizeof(event));
    event.events = EPOLLIN | EPOLLET;
    event.data.fd = fd;
    
    if(epoll_ctl(epoll_fd,EPOLL_CTL_DEL,fd,&event) < 0)
    {
        printf("epoll_ctl EPOLL_CTL_DEL failed !\n");
        return -1;
    }
    
    return 0;
}

int main()
{
    int i = 0;
    int fd = 0;
    int client_fd = 0;
    char *buff = NULL;
    char *buff_new = NULL;
    int buff_size = MAX_BUFF_SIZE;
    int len = 0;
    int recvlen = 0;
    struct epoll_event events[MAX_EPOLL_SIZE];
    int event_num = 0;

    struct sockaddr_in addr;
    bzero(&addr,sizeof(addr));
    socklen_t sock_len = sizeof(struct sockaddr_in);
    memset(events,0,MAX_EPOLL_SIZE);
    while(fd <= 0)
    {
        fd = init_network();
        sleep(1);
    }
    
    while(epoll_fd <= 0)
    {
        init_epoll();
        sleep(1);
    }
    
    buff = (char *)malloc(MAX_BUFF_SIZE);
    if(NULL == buff)
    {
        printf("malloc failed!\n");
    }
    
    add_epoll_ctl(fd);

    while(1)
    {
        event_num = epoll_wait(epoll_fd,events,MAX_EPOLL_SIZE,MAX_EPOLL_TIMEOUT);
        printf("event_num = %d\n",event_num);
        for(i=0;i<event_num;i++)
        {
            client_fd = 0;
            len = 0;
            if(events[i].data.fd == fd) //new connect, do accept
            {
                client_fd = accept(fd,(struct sockaddr *)&addr,&sock_len);
                if(client_fd < 0)
                {
                    printf("accept failed !\n");
                    continue;
                }
                set_fd_nonblocking(client_fd);
                add_epoll_ctl(client_fd);
            }
            else if(events[i].events & EPOLLIN) //do recv
            {
                pthread_mutex_lock(&mutex);
                buff = (char *)malloc(MAX_BUFF_SIZE);
                if(NULL == buff)
                {
                    printf("malloc failed!\n");
                    pthread_mutex_unlock(&mutex);
                    break;
                }
                memset(buff,0,MAX_BUFF_SIZE);

                len = recv(events[i].data.fd,buff,MAX_BUFF_SIZE,0);
                recvlen = len;

                if((len < 0 && errno != EINTR && errno != EWOULDBLOCK && errno != EAGAIN) || len == 0)
                {
                    del_epoll_ctl(events[i].data.fd);
                    close(events[i].data.fd);
                }
                else if(len > 0)
                {
                    if(len == MAX_BUFF_SIZE)
                    {
                        while(len == MAX_BUFF_SIZE)
                        {
                            len = 0;
                            buff_size += MAX_BUFF_SIZE;
                            buff_new = (char *)realloc(buff,buff_size);
                            if(buff_new == NULL)
                            {
                                printf("realloc failed!\n");
                                break;
                            }
                            buff = buff_new;
                            len = recv(events[i].data.fd,&buff[recvlen],MAX_BUFF_SIZE,0);
                            if(len > 0)
                            {
                                recvlen += len;
                            }
                            else if((len < 0 && errno != EINTR && errno != EWOULDBLOCK && errno != EAGAIN) || len == 0)
                            {
                                del_epoll_ctl(events[i].data.fd);
                                close(events[i].data.fd);
                            }


                        }

                        do_tcp(events[i].data.fd,addr,buff,recvlen);
                    }
                    else
                    {
                        do_tcp(events[i].data.fd,addr,buff,recvlen);
                    }

                }
                
                free(buff);
                buff = NULL;
                pthread_mutex_unlock(&mutex);
            }
        }
    }

    pthread_mutex_destroy(&mutex);    
    del_epoll_ctl(fd);
    close(fd);
    close(epoll_fd);
    return 0;
}
发布了5 篇原创文章 · 获赞 1 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/jiust12138/article/details/102563896