epoll回声Server端实现

本文介绍了一个使用Epoll实现的多路复用TCP服务器。该服务器能够同时处理多个客户端连接,并通过Epoll机制高效地管理这些连接。文章详细展示了如何创建服务器套接字、绑定端口、监听连接请求以及如何利用Epoll机制来处理客户端的读写事件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<sys/epoll.h>

void error_handling(char *message);

#define BUFF_SIZE 100
#define EPOLL_SIZE 30

int main(int argc, char *argv[])
{
    int sock_server;
    int sock_client;

    struct sockaddr_in addr_server;
    struct sockaddr_in addr_client;
    socklen_t size_addr_client;

    char buff[BUFF_SIZE];
    int str_len, i;

    int epfd, count_event;
    struct epoll_event *ep_events;
    struct epoll_event event;


    if(argc!=2){ //命令行中启动服务程序仅限一个参数:端口号
        printf("Usage : %s <port>\n", argv[0]);
        exit(1);
    }

    //调用socket函数创建套接字
    sock_server = socket(PF_INET, SOCK_STREAM, 0);
    if(-1 == sock_server){
        error_handling("socket() error.");
    }

    memset(&addr_server, 0, sizeof(addr_server));
    addr_server.sin_family = AF_INET;
    addr_server.sin_addr.s_addr = htonl(INADDR_ANY);
    addr_server.sin_port = htons(atoi(argv[1]));

    //调用bind函数分配IP地址和端口号
    if( -1 == bind( sock_server, (struct sockaddr*)&addr_server, 
                sizeof(addr_server)) ){
        error_handling("bind() error");
    }

    //监听端口的连接请求,连接请求等待队列size为5
    if( -1 == listen(sock_server, 5) ){
        error_handling("listen() error");
    }

    //epoll
    epfd = epoll_create(EPOLL_SIZE);
    //epfd = epoll_create(0); //epoll_wait() Error
    ep_events = (struct epoll_event*)malloc(sizeof(struct epoll_event)*EPOLL_SIZE);

    event.events = EPOLLIN;//监视需用读取数据事件
    event.data.fd=sock_server;
    epoll_ctl(epfd, EPOLL_CTL_ADD, sock_server, &event);
    //
    while(1){
        count_event = epoll_wait(epfd, ep_events, EPOLL_SIZE, -1);
        if(count_event == -1){
            puts("epoll_wait() Error");
            break;
        }

        for(i=0; i<count_event; i++){
            if(ep_events[i].data.fd == sock_server){
                //接受连接请求
                size_addr_client = sizeof(addr_client);
                sock_client = accept( sock_server, (struct sockaddr*)&addr_client, &size_addr_client);
                event.events = EPOLLIN;
                event.data.fd = sock_client;
                epoll_ctl(epfd, EPOLL_CTL_ADD, sock_client, &event);
                printf("Connected client : %d\n", sock_client);
            }else{
                str_len = read(ep_events[i].data.fd, buff, BUFF_SIZE);
                if(str_len){//echo to client
                    buff[str_len] = 0;
                    printf("Message from client %d: %s", i, buff);
                    write(ep_events[i].data.fd, buff, str_len);//echo!
                }else{ //close connection
                    epoll_ctl(epfd, EPOLL_CTL_DEL, ep_events[i].data.fd, NULL);
                    close(ep_events[i].data.fd);
                    printf("Disconnected client %d!\n", ep_events[i].data.fd);
                }
            }//end of if()
        }//end of while
    }//end of for

    //断开连接,关闭套接字
    close(sock_server);
    close(epfd);//

    return 0;
}

void error_handling(char *message)
{
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(EXIT_FAILURE);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值