网络编程---select、poll、epoll服务器编写

select服务器

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>                                                                                                                  
#include <sys/select.h>
#include <sys/socket.h>

#define MAX_FD sizeof(fd_set)*8  //需要进行等待的文件描述符数组最大值
#define INIT -1                  //文件描述符数组初始化值

//文件描述符数组初始化
void AddryInit(int array[], int num )
{
    int i = 0;
    for(; i < num; ++i)
    {
        array[i] = INIT;
    }
}
//往文件描述符数组中添加新的需要等待的文件描述符
void AddryAdd(int array[], int num ,int fd) 
{
    int i = 0;
    for(; i < num; ++i)
    {   
        if(array[i] == INIT)
        {   
            array[i] = fd; 
            return;
        }   
    }   
}
//往可读文件描述符集中添加文件描述符
int ReadFdSet(int listen_sock, int array[], int num , fd_set* read_set)
{
    int i = 0;
    FD_SET(listen_sock, read_set);
    int max = listen_sock;
    for(; i < num; ++i)
    {
        if(array[i] != INIT)
        {
            FD_SET(array[i], read_set);
            if(max < array[i])
            {
                max = array[i];
            }
        }
    }
    return max;
}
//绑定端口号,将套接字设置为监听状态
int StartUp(int port)
{
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if(sock < 0)
    {
        perror("socket");
        exit(1);
    }

    struct sockaddr_in local;
    local.sin_family = AF_INET;
    local.sin_port = htons(port);
    local.sin_addr.s_addr = INADDR_ANY;                                                                                                 
    socklen_t len = sizeof(local);
    if(bind(sock,(struct sockaddr*)&local, len) < 0)
    {
        perror("bind");
        exit(2);
    }
    if(listen(sock,5) < 0)
    {
        perror("listen");
        exit(3);
    }

    return sock;
}
//从文件描述符数组中删除文件描述符
void AddryDel(int array[], int num, int i)
{
    if(i < num)
    {
        array[i] = INIT;
    }
}
//服务函数
void Service(int listen_sock,fd_set* read_set, int array[],int num)
{
    int i = 0;
    for(; i < num ; ++i)
    {
        if(array[i] != INIT && FD_ISSET(array[i],read_set))
        {
            if(array[i] == listen_sock)
            {
                struct sockaddr_in client;
                socklen_t len = sizeof(client);
                int client_sock = accept(listen_sock,(struct sockaddr*)&client, &len);                                                  
                if(client_sock < 0)
                {
                    perror("accept");
                                        continue;
                }
                AddryAdd(array,num,client_sock);
            }
            else
            {
                char buf[1024];
                ssize_t s = read(array[i], buf, sizeof(buf)-1);
                if(s > 0)
                {
                    buf[s] = 0;
                    printf("Client> %s\n",buf);
                }else if(s == 0)
                {
                    printf("client quit...\n");
                    AddryDel(array,num,i);
                }else
                {
                    perror("read");
                }
            }
        }
    }
}
int main(int argc, char* argv[])
{
    if(argc != 2)
    {
        printf("Usage: [%s] [port]\n",argv[0]);
        return 1;
    }

    int listen_sock = StartUp(atoi(argv[1]));

    int array[MAX_FD];
  AddryInit(array,MAX_FD);
    AddryAdd(array,MAX_FD,listen_sock);

    fd_set read_set;
    FD_ZERO(&read_set);

    struct timeval timeout = {5,0};
    for(;;)
    {
        int max = ReadFdSet(listen_sock,array, MAX_FD, &read_set);
        switch(select(max+1,&read_set,NULL,NULL,&timeout))
        {
        case 0:
            sleep(2);
            printf("select timeout...\n");
            break;
        case -1:
            perror("select");
            break;
        default:
            Service(listen_sock,&read_set,array,MAX_FD);
            break;
        }
    FD_ZERO(&read_set);
    }
}                

poll服务器

#include <stdio.h>                                                                                                                      
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <poll.h>
#include <sys/socket.h>

//将poll_fd结构体存储到一个数组中
#define MAX_FD 1024  //需要进行等待的文件描述符数组最大值
#define INIT -1                  //文件描述符数组初始化值
//poll_fd数组初始化
void Init(struct pollfd* fd_list, int num )
{
    int i = 0;
    for(; i < num; ++i)
    {   
        fd_list[i].fd = INIT;
        fd_list[i].events = 0;
        fd_list[i].revents = 0;
    }   
}
//往文件描述符数组中添加新的需要等待的文件描述符
void Add(struct pollfd* fd_list, int num ,int fd) 
{
    int i = 0;
    for(; i < num; ++i)
    {   
        if(fd_list[i].fd == INIT)
        {   
            fd_list[i].fd = fd; 
            fd_list[i].events = POLLIN;
            return;
        }   
    }
}
//绑定端口号,将套接字设置为监听状态
int StartUp(int port)
{
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if(sock < 0)
    {
        perror("socket");
        exit(1);
    }

    struct sockaddr_in local;
    local.sin_family = AF_INET;
    local.sin_port = htons(port);
    local.sin_addr.s_addr = INADDR_ANY;
    socklen_t len = sizeof(local);
    if(bind(sock,(struct sockaddr*)&local, len) < 0)
    {
        perror("bind");
        exit(2);
    }
    if(listen(sock,5) < 0)
    {
        perror("listen");
        exit(3);
    }

    return sock;
}
//服务函数
void Service(int listen_sock,struct pollfd* fd_list,int num)                                                                            
{
    int i = 0;
    for(; i < num ; ++i)
   {
        if(fd_list[i].fd != INIT && fd_list[i].revents & POLLIN )//对应的文件描述符上的读事件就绪
        {
            if(fd_list[i].fd == listen_sock)
            {
                struct sockaddr_in client;
                socklen_t len = sizeof(client);
                int client_sock = accept(listen_sock,(struct sockaddr*)&client, &len);
                if(client_sock < 0)
                {
                    perror("accept");
                    continue;
                }
                Add(fd_list,MAX_FD,client_sock);
            }
            else
            {
                char buf[1024];
                ssize_t s = read(fd_list[i].fd, buf, sizeof(buf)-1);
                if(s > 0)
                {
                    buf[s] = 0;
                    printf("Client> %s\n",buf);
                }else if(s == 0)
                {
                    printf("client quit...\n");
                    close(fd_list[i].fd);
                    fd_list[i].fd = INIT;
                }else
                {
                    perror("read");
                }                                                                                                                       
            }
        }
    }
}
int main(int argc, char* argv[])
{
    if(argc != 2)
    {
        printf("Usage: [%s] [port]\n",argv[0]);
        return 1;
    }

    int listen_sock = StartUp(atoi(argv[1]));

    struct pollfd fd_list[MAX_FD];
    Init(fd_list,MAX_FD);
    Add(fd_list,MAX_FD,listen_sock);

    for(;;)
    {
        switch(poll(fd_list,MAX_FD,1000))
        {
        case 0:
            sleep(2);
            printf("select timeout...\n");
            break;
        case -1:
            perror("select");
            break;
        default:
            Service(listen_sock,fd_list,MAX_FD);
            break;
        }
    }
}            

epoll服务器(LT模式)

ET模式的epoll服务器还没写,等写完了再放上来。。。

#include <stdio.h>                                                                                                                      
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <string.h>
#define MAXEVENTS 10

//打印提示手册
void Usage()
{
    printf("Usage: ./epoll_server.c [port]\n");
    exit(0);
}

//创建监听套接字
int StartUp(int port)
{
    int sock = socket(AF_INET, SOCK_STREAM, 0); 
    if(sock < 0)
    {   
        perror("socket");
        exit(1);
    }   

    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons(port);

    if(bind(sock,(struct sockaddr*)&server, sizeof(server)) < 0)
    {   
        perror("bind");
        exit(2);
    }

    if(listen(sock,5) < 0)
    {
        perror("listen");
        exit(3);
    }
    return sock;
}
//服务函数
void Server(int listen_sock, int epoll_fd, struct epoll_event re_epoll_event[], int num)
{
    int i = 0;
    for(;i < num;++i)
    {
        if(re_epoll_event[i].events & EPOLLIN){
            if(re_epoll_event[i].data.fd == listen_sock && re_epoll_event[i].events & EPOLLIN)
            {
                struct sockaddr_in client;
                socklen_t len = sizeof(client);
                int client_sock = accept(re_epoll_event[i].data.fd,(struct sockaddr*)&client,&len);
                if(client_sock < 0)
                {
                    perror("accept");
                    continue;
                }
                printf("Client[%s] accept success!\n",inet_ntoa(client.sin_addr));
                struct epoll_event event;
                event.data.fd = client_sock;
                event.events = EPOLLIN | EPOLLOUT;                                                                                      
                epoll_ctl(epoll_fd,EPOLL_CTL_ADD,client_sock,&event);
                continue;
            }
            else
            {
                char buf[1024];
                buf[0] = '\0';
                ssize_t s = recv(re_epoll_event[i].data.fd,buf,sizeof(buf)-1,0);
                if(s > 0)
                {
                    buf[s] = '\0';
                    printf("Client> %s\n",buf);
                    send(re_epoll_event[i].data.fd,buf,strlen(buf),0);
                    continue;
                }else if(s == 0)
                {
                    printf("Client quit\n");
                    epoll_ctl(epoll_fd,EPOLL_CTL_DEL,re_epoll_event[i].data.fd,NULL);
                    close(re_epoll_event[i].data.fd);
                    continue;
                }
                else
                {
                    perror("recv");
                    continue;
                }
            }
        }
    }
}

int main(int argc, char* argv[])
{
    if(argc != 2)
        Usage();                                                                                                                        
    int listen_sock = StartUp(atoi(argv[1]));

    //创建epoll模型
    int epoll_fd = epoll_create(MAXEVENTS+1);
    if(epoll_fd == -1)
    {
        perror("epoll_create");
        return 1;
    }
    //向epoll模型中添加文件描述符并注册事件
    struct epoll_event epoll_event;
    epoll_event.events = EPOLLIN;
    epoll_event.data.fd = listen_sock;

    //接收epoll_wait返回值
    if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_sock,&epoll_event ) < 0)
    {
        perror("epoll_ctl");
        return 2;
    }
    for(;;)
    {
        struct epoll_event re_epoll_event[MAXEVENTS];
        int ret = epoll_wait(epoll_fd,re_epoll_event,MAXEVENTS,-1);
        switch(ret)
        {
        case 0:
            printf("epoll_wait timeout...\n");
            break;
        case -1:
            perror("epoll_wait");
            break;
        default:
            Server(listen_sock,epoll_fd,re_epoll_event,ret);                                                                            
            break;
        }
    }
    return 0;
}     
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值