epoll实现简单echo服务器

好久没写过博客了,之前写博客纯属是为了记录,防止再遇到同样的问题一时想不起来,可以查查博客。然后发现印象笔记好像挺好用,然后就懒得写博客了。。。
最近感觉心态变了,写博客当自己学习过程的分享吧。
这篇博客内容不深,甚至是烂大街的东西,纯属是表达一下我学习的思路,希望可以给和我一样的新手一些学习的思路,写的不好的也请勿喷,谢谢

epoll的概念,还有什么与select、poll等的区别,优缺点,请自行搜索引擎,本人自认为还没到那水平,没法说明。

Linux编程,我认为,很重要的技能之一就是要学会是用man page(别跟我说英语不好巴拉巴拉的,吃得苦中苦,方为人上人),就比如本博文中要用到epoll,直接在终端中输入:

//$是终端指示符
$man epoll

然后就出现了各种关于epoll的说明,什么DESCRIPTION, EXAMPLE,Questions and Answers啊,等等,啃,耐心的啃完,看不懂就查,查到懂(反正我是这么过来)。

从说明中可以看到,epoll主要就是,epoll_create1,epoll_ctl,epoll_wait这几个函数,还有就是ET、LT等,这时候就可以相应的查看函数的具体信息了:

$man epoll_reate1

又是各种说明,还能怎样,继续啃咯。。。
对别的函数进行同样的操作,行了,结果就出来了。。。
同时恭喜你向着大神方向又进了一步。。。
加油!!!

附上代码,也可到github.com/guanlaolin/echo 上获取代码(建议,因为我可能会修改代码)

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

const int SERVER_PORT = 8000;
const char SERVER_ADDR[] = "127.0.0.1";
const int MAX_CLIENT = 100;
const int MAX_SIZE = 1024;

int main()
{
    //definiton
    int sock,client_sock;
    char buff[MAX_SIZE];
    sockaddr_in server_addr,client_addr;
    epoll_event event,events[MAX_CLIENT];

    //initialaziton
    bzero(&server_addr, sizeof(sockaddr_in));
    bzero(&client_addr, sizeof(client_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    server_addr.sin_addr.s_addr = inet_addr(SERVER_ADDR);

    sock = socket(AF_INET, SOCK_STREAM, 0);
    if ( -1 == sock )
    {
        perror("socket error");
        return -1;
    }

    if (bind( sock, (sockaddr *)&server_addr, sizeof(sockaddr)) == -1)
    {
        perror("bind error");
        return -1;
    }

    if ( listen( sock, MAX_CLIENT) == -1)
    {
        perror("listen error");
        return -1;
    }

    //epoll begin
    //创建epoll
    int epfd = epoll_create1(0);
    if (-1 == epfd)
    {
        perror("epoll create");
        return -1;
    }

    //添加sock到epoll,监听连接事件
    bzero(&event, sizeof(epoll_event));
    event.events = EPOLLIN;
    event.data.fd = sock;

    if (epoll_ctl(epfd, EPOLL_CTL_ADD, sock, &event) == -1)
    {
        perror("epoll ctl");
        return -1;
    }

    for(;;)
    {
        int nfds = epoll_wait(epfd, events, MAX_CLIENT, -1);
        if (-1 == nfds)
        {
            perror("epoll wait");
            continue;
        }
        for( int i = 0; i < nfds; ++i)
        {
            if (events[i].data.fd == sock)  //有连接
            {
                //accept
                socklen_t client_addr_size = sizeof(sockaddr);
                client_sock = accept(sock, (sockaddr *)&client_addr, &client_addr_size);
                if (-1 == client_sock)
                {
                    perror("accept error");
                    continue;
                }
                printf("accept client:%s:%u\n",inet_ntoa(client_addr.sin_addr), ntohl(client_addr.sin_port));

                //将client注册到epoll
                bzero(&event, sizeof(epoll_event));
                event.events = EPOLLIN;
                event.data.fd = client_sock;
                if (epoll_ctl(epfd, EPOLL_CTL_ADD, client_sock, &event) == -1)
                {
                    perror("epoll ctl");
                    continue;
                }
            }else if (events[i].events & EPOLLIN)   //读事件
            {
                //读取数据
                if (read(events[i].data.fd, buff, MAX_SIZE) == -1)
                {
                    perror("read error");
                    continue;
                }
                printf("Read data from client:%s\n", buff);

                //设置为可写
                //将client注册到epoll
                bzero(&event, sizeof(epoll_event));
                event.events = EPOLLOUT;
                event.data.fd = events[i].data.fd;
                if (epoll_ctl(epfd, EPOLL_CTL_MOD, events[i].data.fd, &event) == -1)
                {
                    perror("epoll ctl");
                    continue;
                }
            }else if (events[i].events & EPOLLOUT)  //写事件
            {
                //网客户端写入当前时间
                time_t t = time(NULL);
                if ( (time_t)-1 == t)
                {
                    perror("time");
                    continue;
                }

                char *now = asctime(gmtime(&t));

                if (write( events[i].data.fd, now, strlen(now)) == -1)
                {
                    perror("write error");
                    continue;
                }
                //设置为可读
                //将client注册到epoll
                bzero(&event, sizeof(epoll_event));
                event.events = EPOLLIN;
                event.data.fd = events[i].data.fd;
                if (epoll_ctl(epfd, EPOLL_CTL_MOD, events[i].data.fd, &event) == -1)
                {
                    perror("epoll ctl");
                    continue;
                }
            }else if(events[i].events & EPOLLHUP)
            {
                //删除
                bzero(&event, sizeof(epoll_event));
                event.events = EPOLLHUP;
                if (epoll_ctl(epfd,EPOLL_CTL_DEL, events[i].data.fd, &event) == -1)
                {
                    perror("epoll ctl");
                    continue;
                }
                printf("客户端关闭\n");
            }
            else
            {
                printf("未实现的处理事件:%d\n",events[i].events);
                continue;
            }
        }
    }

    close(epfd);
    close(client_sock);
    close(sock);

    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值