c/c++ linux epoll系列1 创建epoll

linux epoll系列1 创建epoll

据说select和poll的弱点是,随着连接(socket)的增加,性能会直线下降。

epoll不会随着连接(socket)的增加,性能直线下降。

知识点:

1,epoll_wait函数是阻塞的,直到有socket发生变化。

2,epoll使用流程,先创建(epoll_create),再把socket添加到epoll里(epoll_ctl),然后等待socket的变化(epoll_wait)

接收端,接收2个socket

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

#define EVENTS 12

int main(){
  int sock1, sock2;
  sockaddr_in addr1, addr2;
  int epfd;
  epoll_event ev, ev_ret[EVENTS];
  char buf[2048];
  int i;
  int nfds;
  int n;

  //创建2个接受消息的socket
  sock1 = socket(AF_INET, SOCK_DGRAM, 0);
  sock2 = socket(AF_INET, SOCK_DGRAM, 0);
  addr1.sin_family = AF_INET;
  addr2.sin_family = AF_INET;

  inet_pton(AF_INET, "127.0.0.1", &addr1.sin_addr.s_addr);
  inet_pton(AF_INET, "127.0.0.1", &addr2.sin_addr.s_addr);

  addr1.sin_port = htons(11111);
  addr2.sin_port = htons(22222);

  bind(sock1, (sockaddr*)&addr1, sizeof(addr1));
  bind(sock2, (sockaddr*)&addr2, sizeof(addr2));

  //参数不小于0就行
  epfd = epoll_create(1);
  if(epfd < 0){
    perror("epoll_create");
    return 1;
  }

  memset(&ev, 0, sizeof(ev));
  ev.events = EPOLLIN;//只读
  ev.data.fd = sock1;//把sock1加到epoll
  if(epoll_ctl(epfd, EPOLL_CTL_ADD, sock1, &ev) != 0){
    perror("epoll_ctl");
    return 1;
  }

  memset(&ev, 0, sizeof(ev));
  ev.events = EPOLLIN;//只读
  ev.data.fd = sock2;//把sock2加到epoll
  if(epoll_ctl(epfd, EPOLL_CTL_ADD, sock2, &ev) != 0){
    perror("epoll_ctl");
    return 1;
  }

  while(1){
    printf("before epoll_wait\n");
    //在这里会阻塞,直到有socket进来.
    nfds = epoll_wait(epfd, ev_ret, EVENTS, -1);
    if(nfds <= 0){
      perror("epoll_wait");
      return 1;
    }

    printf("after epoll_wait\n");

    for(i = 0; i < nfds; ++i){
      //判断进来的socket是哪个socket
      if(ev_ret[i].data.fd == sock1){
    //从sock1读取数据,并写入到标准输出
    n = recv(sock1, buf, sizeof(buf), 0);
    write(fileno(stdout), buf, n);
      }
      //判断进来的socket是哪个socket
      else if(ev_ret[i].data.fd == sock2){
    //从sock1读取数据,并写入到标准输出
    n = recv(sock2, buf, sizeof(buf), 0);
    write(fileno(stdout), buf, n);
      }
    }
  }

  close(sock1);
  close(sock2);
  return 0;
}

github源代码

发送端,向2个地址发送信息

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

int main(){
  int sock;
  sockaddr_in dest1, dest2;
  char buf[1024];

  sock = socket(AF_INET, SOCK_DGRAM, 0);

  dest1.sin_family = AF_INET;
  dest2.sin_family = AF_INET;

  inet_pton(AF_INET, "127.0.0.1", &dest1.sin_addr.s_addr);
  inet_pton(AF_INET, "127.0.0.1", &dest2.sin_addr.s_addr);

  dest1.sin_port = htons(11111);
  dest2.sin_port = htons(22222);

  strcpy(buf, "data to port 11111\n");
  //给地址1(dest1)送信
  sendto(sock, buf, strlen(buf), 0, (sockaddr*)&dest1, sizeof(dest1));

  strcpy(buf, "data to port 22222\n");
  //给地址2(dest2)送信
  sendto(sock, buf, strlen(buf), 0, (sockaddr*)&dest2, sizeof(dest1));

  close(sock);

  return 0;
}

github源代码

运行方法:

先运行接收端,结果如下:

before epoll_wait

再运行发送端,结果如下:

before epoll_wait
after epoll_wait
data to port 11111
before epoll_wait
after epoll_wait
data to port 22222
before epoll_wait

从运行结果可以看出:在epoll_wait处,程序的停住的,也就是阻塞的状态,但是当运行发送端后,马上就变成了非阻塞状态,也就实现了,处理多个socket的请求,而并没有使用多进程,或者多线程。

c/c++ 学习互助QQ群:877684253

本人微信:xiaoshitou5854

原文地址:https://www.cnblogs.com/xiaoshiwang/p/9824439.html

时间: 2024-10-13 00:25:45

c/c++ linux epoll系列1 创建epoll的相关文章

c/c++ linux epoll系列3 利用epoll_wait设置timeout时间长度

linux epoll系列3 利用epoll_wait设置timeout时间长度 epoll_wait函数的第四个参数可以设置,epoll_wait函数的等待时间(timeout时间长度). 例子1,是接收端. 例子2,是发送端. 例子1,接收端 #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h

linux网络编程-----&gt;高并发---&gt;epoll多路I/O转接服务器

做网络服务的时候并发服务端程序的编写必不可少.前端客户端应用程序是否稳定一部分取决于客户端自身,而更多的取决于服务器是否相应时间够迅速,够稳定. 常见的linux并发服务器模型: 多进程并发服务器 多线程并发服务器 select多路I/O转接服务器 poll多路I/O转接服务器 epool多路I/O转接服务器. 本次主要讨论poll多路I/转接并发服务器模型: 前几章介绍完了多进程并发服务器,  多线程并发服务器, selete多路I/O转接服务器,  poll多路I/O转接服务器, 本章开始介

Linux下多路复用IO接口epoll/select/poll的区别

select比epoll效率差的原因:select是轮询,epoll是触发式的,所以效率高. Select: 1.Socket数量限制:该模式可操作的Socket数由FD_SETSIZE决定,内核默认32*32=1024. 2.操作限制:通过遍历FD_SETSIZE(1024)个Socket来完成调度,不管哪个Socket是活跃的,都遍历一遍. Poll: 1.Socket数量几乎无限制:该模式下的Socket对应的fd列表由一个数组来保存,大小不限(默认4k). 2.操作限制:同Select.

Linux中select poll和epoll的区别

在Linux Socket服务器短编程时,为了处理大量客户的连接请求,需要使用非阻塞I/O和复用,select.poll和epoll是Linux API提供的I/O复用方式,自从Linux 2.6中加入了epoll之后,在高性能服务器领域得到广泛的应用,现在比较出名的nginx就是使用epoll来实现I/O复用支持高并发,目前在高并 发的场景下,nginx越来越收到欢迎.这里有个文章参考.Nginx成为全球Top1000网站最受欢迎的Web服务器. 据 w3techs 7月 3 日的统计数据表明

linux高性能服务器编程之epoll

一.概述: epoll是多路复用的一种,但它比select和poll更加高效.具体体现在以下几个方面: (1).select能打开的文件描述符是有一定限制的,默认情况下是2048,这对应那些大型服务器来说h是不足的.但 epoll则没有这个限制,它所支持的fd上限是最大可以打开文件的数目,这个数字一般远大于2048,举个例子,在1GB内存的机器上大约是10万左 右,具体数目可以cat  /proc/sys/fs/file-max察看,一般来说这个数目和系统内存关系很大. (2).因为文件描述符是

Linux下select, poll和epoll IO模型的详解(转)

http://blog.csdn.net/tianmohust/article/details/6677985 一).Epoll 介绍 Epoll 可是当前在 Linux 下开发大规模并发网络程序的热门人选, Epoll 在 Linux2.6 内核中正式引入,和 select 相似,其实都 I/O 多路复用技术而已 ,并没有什么神秘的.其实在 Linux 下设计并发网络程序,向来不缺少方法,比如典型的 Apache 模型( Process Per Connection ,简称 PPC ), TP

c/c++ llinux epoll系列5 解除epoll_wait状态

linux epoll系列5 解除epoll_wait状态 有时候会有解除epoll_wait状态的需求. 实现方法: 1,给执行epoll_wait的程序发signal. 2,使用sockpair. 1,给执行epoll_wait的程序发signal. #include <stdio.h> #include <unistd.h> #include <signal.h> #include <errno.h> #include <sys/epoll.h&

Linux网络编程——多路复用之epoll

目录 Linux网络编程--多路复用之epoll 基础API 实例一.epoll实现在线聊天 实例二.epoll实现在客户端断开后服务端能一直运行,客户端可以多次重连 Linux网络编程--多路复用之epoll ? epoll是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率,因为它会复用文件描述符集合来传递结果而不用迫使开发者每次等待事件之前都必须重新准备要被侦听的文件描述符集合,另一点原因就是获取事件的时候,

c/c++ llinux epoll系列4 利用epoll_wait实现非阻塞的connect

llinux epoll系列4 利用epoll_wait实现非阻塞的connect connect函数是阻塞的,而且不能设置connect函数的timeout时间,所以一旦阻塞太长时间,影响用户的体验,所以就出来一个需求,硬要设置connect的timeout时间. 实现方法:先把connect函数变成非阻塞的,然后用设置epoll_wait的timeout时间,用epoll_wait等待connect的完成. #include <stdio.h> #include <unistd.h&