由epoll实现的简易服务端实例

函数原型:

#include <sys/epoll.h>
int epoll_create(int size);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

函数解析:

1 .epoll_create:创建epoll句柄,占一个fd值,需要用close释放

2. epoll_ctl:事件注册函数,与select选择监听什么类型的事件不同,epoll由此函数注册要监听的事件是什么类型的

(1)参数epfd:由epoll_create创建的fd

(2)参数op:表示要执行哪种操作,由三个宏区分

​ EPOLL_CTL_ADD:注册新的fd到epfd中; 

​ EPOLL_CTL_MOD:修改已经注册的fd的监听事件;

​ EPOLL_CTL_DEL:从epfd中删除一个fd。

(3)参数fd:需要监听的套接字fd

(4)参数event:要监听的事件类型是什么,大体分为:

​ EPOLLIN:表示对应的文件描述符可读; EPOLLOUT:表示对应的文件描述符可写; EPOLLPRI:表示对应的文件描述符有紧急数据可读; EPOLLERR:表示对应的文件描述符发生错误; EPOLLHUP:表示对应的文件描述符被挂断; EPOLLET:将EPOLL设为边缘触发(只有数据到来才触发,不管缓存区的其他数据),这是相对于水平触发(只要有数据就触发)而言的。 

3. epoll_wait :用于收集在epoll监控的事件中已经发生的事件,返回值为发生的事件个数;

(1)参数events:是个epoll_event结构体数组的指针,得自己申请空间,不能放空指针

(2)参数maxevents:events数组有多大,值不能大于初始化create时后的size

(3)timeout:超时时间


#include <iostream>
#include "common_n.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <sys/ioctl.h>
#define MAX_N 200
#define PORT 8888
using namespace std;

int main() {
    int listen_socket = socket_create(PORT);
    int ep_fd = epoll_create(MAX_N);
    if (ep_fd < 0) {
        perror("epoll_create");
        exit(1);
    }
    struct epoll_event ev, events[MAX_N];
    ev.data.fd = listen_socket;
    ev.events = EPOLLIN | EPOLLET;
    if (epoll_ctl(ep_fd, EPOLL_CTL_ADD, listen_socket, &ev) < 0) {
        perror("epoll_ctl");
        exit(0);
    }
    unsigned long ul = 1;
    ioctl(listen_socket, FIONBIO, &ul);
    int nfds;
    while (1) {
        nfds = epoll_wait(ep_fd, events, MAX_N, 5*1000);
        if (nfds < 0) {
            perror("epoll_wait");
            exit(1);
        }
        if (nfds == 0) {
            cout << "time out" << endl;
        }
        for (int i = 0; i < nfds; i++) {
            //加入
            if (events[i].data.fd == listen_socket) {
                int new_sock = accept(listen_socket, NULL, NULL);
                if(new_sock < 0) {
                    perror("accept");
                    exit(1);
                }
                cout << "someone comes" << endl;
                ioctl(new_sock, FIONBIO, &ul);
                ev.data.fd = new_sock;
                ev.events = EPOLLIN | EPOLLET;
                if (epoll_ctl(ep_fd, EPOLL_CTL_ADD, new_sock, &ev) < 0){
                    perror("epoll_ctl : new_sock");
                    nfds += 1;
                    continue;
                }
            } else { //通讯
                int client_fd = events[i].data.fd;
                char buff[1024] = {0};
                    struct sockaddr_in addr;
                    socklen_t len = sizeof(addr);
                    getpeername(client_fd, (struct sockaddr*)&addr, &len);
                    if (recv(client_fd, buff, 1024, 0) <= 0) {
                        cout << "some leave" << endl;
                        epoll_ctl(ep_fd, EPOLL_CTL_DEL, client_fd, &ev);
                        close(client_fd);
                        nfds --;
                        continue;
                    }
                    //printf("%s : %s",inet_ntoa(addr.sin_addr), buff);
                    cout << inet_ntoa(addr.sin_addr) << "--->" << buff << endl;
                    send(client_fd, buff, strlen(buff), 0); 
            }
        }
    }
    close(listen_socket);
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值