热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

LinuxIO多路复用之epoll网络编程

今天小编就为大家分享一篇关于LinuxIO多路复用之epoll网络编程,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

前言

本章节是用基本的Linux基本函数加上epoll调用编写一个完整的服务器和客户端例子,可在Linux上运行,客户端和服务端的功能如下:

  • 客户端从标准输入读入一行,发送到服务端
  • 服务端从网络读取一行,然后输出到客户端
  • 客户端收到服务端的响应,输出这一行到标准输出

服务端

代码如下:

#include 
#include     /* basic system data types */
#include    /* basic socket definitions */
#include    /* sockaddr_in{} and other Internet defns */
#include     /* inet(3) functions */
#include  /* epoll function */
#include    /* nonblocking */
#include  /*setrlimit */
#include 
#include 
#include 
#include 
#define MAXEPOLLSIZE 10000
#define MAXLINE 10240
int handle(int connfd);
int setnonblocking(int sockfd)
{
  if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1) {
    return -1;
  }
  return 0;
}
int main(int argc, char **argv)
{
  int servPort = 6888;
  int listenq = 1024;
  int listenfd, connfd, kdpfd, nfds, n, nread, curfds,acceptCount = 0;
  struct sockaddr_in servaddr, cliaddr;
  socklen_t socklen = sizeof(struct sockaddr_in);
  struct epoll_event ev;
  struct epoll_event events[MAXEPOLLSIZE];
  struct rlimit rt;
  char buf[MAXLINE];
  /* 设置每个进程允许打开的最大文件数 */
  rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE;
  if (setrlimit(RLIMIT_NOFILE, &rt) == -1) 
  {
    perror("setrlimit error");
    return -1;
  }
  bzero(&servaddr, sizeof(servaddr));
  servaddr.sin_family = AF_INET; 
  servaddr.sin_addr.s_addr = htonl (INADDR_ANY);
  servaddr.sin_port = htons (servPort);
  listenfd = socket(AF_INET, SOCK_STREAM, 0); 
  if (listenfd == -1) {
    perror("can't create socket file");
    return -1;
  }
  int opt = 1;
  setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
  if (setnonblocking(listenfd) <0) {
    perror("setnonblock error");
  }
  if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) == -1) 
  {
    perror("bind error");
    return -1;
  } 
  if (listen(listenfd, listenq) == -1) 
  {
    perror("listen error");
    return -1;
  }
  /* 创建 epoll 句柄,把监听 socket 加入到 epoll 集合里 */
  kdpfd = epoll_create(MAXEPOLLSIZE);
  ev.events = EPOLLIN | EPOLLET;
  ev.data.fd = listenfd;
  if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, listenfd, &ev) <0) 
  {
    fprintf(stderr, "epoll set insertion error: fd=%d\n", listenfd);
    return -1;
  }
  curfds = 1;
  printf("epollserver startup,port %d, max connection is %d, backlog is %d\n", servPort, MAXEPOLLSIZE, listenq);
  for (;;) {
    /* 等待有事件发生 */
    nfds = epoll_wait(kdpfd, events, curfds, -1);
    if (nfds == -1)
    {
      perror("epoll_wait");
      continue;
    }
    /* 处理所有事件 */
    for (n = 0; n = MAXEPOLLSIZE) {
          fprintf(stderr, "too many connection, more than %d\n", MAXEPOLLSIZE);
          close(connfd);
          continue;
        } 
        if (setnonblocking(connfd) <0) {
          perror("setnonblocking error");
        }
        ev.events = EPOLLIN | EPOLLET;
        ev.data.fd = connfd;
        if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, connfd, &ev) <0)
        {
          fprintf(stderr, "add socket '%d' to epoll failed: %s\n", connfd, strerror(errno));
          return -1;
        }
        curfds++;
        continue;
      } 
      // 处理客户端请求
      if (handle(events[n].data.fd) <0) {
        epoll_ctl(kdpfd, EPOLL_CTL_DEL, events[n].data.fd,&ev);
        curfds--;
      }
    }
  }
  close(listenfd);
  return 0;
}
int handle(int connfd) {
  int nread;
  char buf[MAXLINE];
  nread = read(connfd, buf, MAXLINE);//读取客户端socket流
  if (nread == 0) {
    printf("client close the connection\n");
    close(connfd);
    return -1;
  } 
  if (nread <0) {
    perror("read error");
    close(connfd);
    return -1;
  }  
  write(connfd, buf, nread);//响应客户端 
  return 0;
}

编译

编译和启动服务端

gcc epollserver.c -o epollserver
./epollserver

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。如果你想了解更多相关内容请查看下面相关链接


推荐阅读
  • 本文探讨了服务器系统架构的性能评估方法,包括性能评估的目的、步骤以及如何选择合适的度量标准。文章还介绍了几种常用的基准测试程序及其应用,并详细说明了Web服务器性能评估的关键指标与测试方法。 ... [详细]
  • WebBenchmark:强大的Web API性能测试工具
    本文介绍了一款名为WebBenchmark的Web API性能测试工具,该工具不仅支持HTTP和HTTPS服务的测试,还提供了丰富的功能来帮助开发者进行高效的性能评估。 ... [详细]
  • 本文回顾了作者在求职阿里和腾讯实习生过程中,从最初的迷茫到最后成功获得Offer的心路历程。文中不仅分享了个人的面试经历,还提供了宝贵的面试准备建议和技巧。 ... [详细]
  • 随着Linux操作系统的广泛使用,确保用户账户及系统安全变得尤为重要。用户密码的复杂性直接关系到系统的整体安全性。本文将详细介绍如何在CentOS服务器上自定义密码规则,以增强系统的安全性。 ... [详细]
  • 2019年独角兽企业招聘Python工程师标准课程概览
    本文详细介绍了2019年独角兽企业在招聘Python工程师时的标准课程内容,包括Shell脚本中的逻辑判断、文件属性判断、if语句的特殊用法及case语句的应用。 ... [详细]
  • Java虚拟机及其发展历程
    Java虚拟机(JVM)是每个Java开发者日常工作中不可或缺的一部分,但其背后的运作机制却往往显得神秘莫测。本文将探讨Java及其虚拟机的发展历程,帮助读者深入了解这一关键技术。 ... [详细]
  • 本文基于Java官方文档进行了适当修改,旨在介绍如何实现一个能够同时处理多个客户端请求的服务端程序。在前文中,我们探讨了单客户端访问的服务端实现,而本篇将深入讲解多客户端环境下的服务端设计与实现。 ... [详细]
  • 服务器虚拟化存储设计,完美规划储存与资源,部署高性能虚拟化桌面
    规划部署虚拟桌面环境前,必须先估算目前所使用实体桌面环境的工作负载与IOPS性能,并慎选储存设备。唯有谨慎估算贴近实际的IOPS性能,才能 ... [详细]
  • 本文介绍了如何使用Node.js通过两种不同的方法连接MongoDB数据库,包括使用MongoClient对象和连接字符串的方法。每种方法都有其特点和适用场景,适合不同需求的开发者。 ... [详细]
  • 本文详细介绍如何安装和配置DedeCMS的移动端站点,包括新版本安装、老版本升级、模板适配以及必要的代码修改,以确保移动站点的正常运行。 ... [详细]
  • Asynchronous JavaScript and XML (AJAX) 的流行很大程度上得益于 Google 在其产品如 Google Suggest 和 Google Maps 中的应用。本文将深入探讨 AJAX 在 .NET 环境下的工作原理及其实现方法。 ... [详细]
  • JavaScript 跨域解决方案详解
    本文详细介绍了JavaScript在不同域之间进行数据传输或通信的技术,包括使用JSONP、修改document.domain、利用window.name以及HTML5的postMessage方法等跨域解决方案。 ... [详细]
  • 本文提供了多种有效的方法来解决RPC(远程过程调用)服务器不可用的问题,包括通过修改注册表、使用SC命令以及利用故障恢复控制台等技术手段。 ... [详细]
  • 问题概述:在本地环境中代码运行正常,但部署到服务器后出现错误。具体表现为NCManager和SAXBuilder无法解析为类型。 ... [详细]
  • 本文详细介绍了如何在CentOS 6.5系统上安装和配置Redis 3.0.6,包括必要的环境准备、软件包下载、编译安装及基本功能测试。 ... [详细]
author-avatar
闹剧-豆腐渣_141
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有