当前位置: 首页 > news >正文

C++回声服务器_9-epoll边缘触发模式版本服务器

epoll默认情况下是水平触发模式,这次将epoll设置为边缘触发模式来实现服务器,而客户端直接使用完美回声服务器的客户端。

服务器代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <cerrno>

const int BUF_SIZE = 4;
const int EPOLL_SIZE = 50;

void setnonblockingmode(int fd);
void error_handling(const char *buf);

int main(int argc, char *argv[]) {
    int server_sock, client_sock;
    sockaddr_in server_addr, client_addr;

    socklen_t addr_size;
    ssize_t str_len;
    int i;
    char buf[BUF_SIZE];

    epoll_event *ep_events;
    epoll_event event;
    int epfd, event_cnt;

    if (argc != 2) {
        printf("Usage : %s <port>\n", argv[0]);
        exit(1);
    }

    server_sock = socket(PF_INET, SOCK_STREAM, 0);
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(atoi(argv[1]));

    if (bind(server_sock, (sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
        error_handling("bind() error");
        exit(1);
    }

    if (listen(server_sock, 5) == -1) {
        error_handling("listen() error");
    }


    epfd = epoll_create(EPOLL_SIZE);
    ep_events = (epoll_event*)malloc(sizeof(epoll_event) * EPOLL_SIZE);

    event.events = EPOLLIN;
    event.data.fd = server_sock;
    epoll_ctl(epfd, EPOLL_CTL_ADD, server_sock, &event);

    while (1) {
        event_cnt = epoll_wait(epfd, ep_events, EPOLL_SIZE, -1);
        if (event_cnt == -1) {
            puts("epoll_wait() error");
            break;
        }

        for (int i = 0; i < event_cnt; ++i) {
            if (ep_events[i].data.fd == server_sock) {
                addr_size = sizeof(client_addr);
                client_sock = accept(server_sock, (sockaddr*)&client_addr, &addr_size);
                setnonblockingmode(client_sock); // 设置client socket为非阻塞模式
                event.events = EPOLLIN | EPOLLET; // 设置epoll边缘触发
                event.data.fd = client_sock;
                epoll_ctl(epfd, EPOLL_CTL_ADD, client_sock, &event);
                printf("connect client: %d\n", client_sock);
            } else {
                while (1) { // 将数据读完为止
                    str_len = read(ep_events[i].data.fd, buf, BUF_SIZE);
                    if (str_len == 0) {
                        epoll_ctl(epfd, EPOLL_CTL_DEL, ep_events[i].data.fd, NULL);
                        close(ep_events[i].data.fd);
                        printf("closed client: %d\n", ep_events[i].data.fd);
                    } else if (str_len < 0) {
                        if (errno == EAGAIN) { // 已无数据
                            break;
                        }
                    }
                    else {
                        write(ep_events[i].data.fd, buf,str_len);
                    }
                }
            }
        }
    }
    close(server_sock);
    close(epfd);

    return 0;
}

// 将文件描述符设置为非阻塞
void setnonblockingmode(int fd) {
    int flag = fcntl(fd, F_GETFL, 0);
    fcntl(fd, F_SETFL, flag | O_NONBLOCK);
}

项目代码

github

参考

《TCP/IP网络编程》

相关文章:

  • 242. Valid Anagram(C++)
  • 冒泡排序及回调函数的使用
  • HTML5基础(四)
  • 决战燕京城-10 前往天寿山
  • ubuntu设置源
  • 据Progress调查:2018年,70%的客户在使用NoSQL
  • PopupWindow
  • mysqldump的实现原理
  • containerd正式从CNCF毕业!
  • java动态代理(JDK和cglib)
  • 巧用年线抓长线牛股的四种经典技巧
  • 说说spring注解
  • 爬虫入门(四)
  • CSS3D效果
  • 诈欺猎物160万+,同盾科技、猛犸等诈欺猎人们的反击战
  • 《深入 React 技术栈》
  • DataBase in Android
  • JS题目及答案整理
  • JS专题之继承
  • leetcode讲解--894. All Possible Full Binary Trees
  • python 装饰器(一)
  • socket.io+express实现聊天室的思考(三)
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • Stream流与Lambda表达式(三) 静态工厂类Collectors
  • sublime配置文件
  • 多线程 start 和 run 方法到底有什么区别?
  • 翻译--Thinking in React
  • 极限编程 (Extreme Programming) - 发布计划 (Release Planning)
  • 前端每日实战:61# 视频演示如何用纯 CSS 创作一只咖啡壶
  • 如何编写一个可升级的智能合约
  • 实现菜单下拉伸展折叠效果demo
  • 说说动画卡顿的解决方案
  • 提醒我喝水chrome插件开发指南
  • 为物联网而生:高性能时间序列数据库HiTSDB商业化首发!
  • ​马来语翻译中文去哪比较好?
  • (3)Dubbo启动时qos-server can not bind localhost22222错误解决
  • (4) openssl rsa/pkey(查看私钥、从私钥中提取公钥、查看公钥)
  • (4)Elastix图像配准:3D图像
  • (c语言版)滑动窗口 给定一个字符串,只包含字母和数字,按要求找出字符串中的最长(连续)子串的长度
  • (DenseNet)Densely Connected Convolutional Networks--Gao Huang
  • (MonoGame从入门到放弃-1) MonoGame环境搭建
  • (附源码)计算机毕业设计SSM保险客户管理系统
  • (转)编辑寄语:因为爱心,所以美丽
  • (转)母版页和相对路径
  • (转)视频码率,帧率和分辨率的联系与区别
  • (转)为C# Windows服务添加安装程序
  • **PHP二维数组遍历时同时赋值
  • .NET Core中Emit的使用
  • .net企业级架构实战之7——Spring.net整合Asp.net mvc
  • .net专家(张羿专栏)
  • /deep/和 >>>以及 ::v-deep 三者的区别
  • /etc/shadow字段详解
  • /etc/skel 目录作用
  • [AR]Vumark(下一代条形码)
  • [BZOJ1040][P2607][ZJOI2008]骑士[树形DP+基环树]