zoukankan      html  css  js  c++  java
  • 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
    ");
        //在这里会阻塞,直到有socket进来.
        nfds = epoll_wait(epfd, ev_ret, EVENTS, -1);
        if(nfds <= 0){
          perror("epoll_wait");
          return 1;
        }
    
        printf("after epoll_wait
    ");
    
        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
    ");
      //给地址1(dest1)送信
      sendto(sock, buf, strlen(buf), 0, (sockaddr*)&dest1, sizeof(dest1));
      
      strcpy(buf, "data to port 22222
    ");
      //给地址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

  • 相关阅读:
    C# NAudio 变声
    初探Protostuff的使用
    CentOS7 配置阿里云yum源,非常之简单
    javacv 视频增加视频(画中画)
    抓包调试fiddler
    CentOS7 手动编译升级GCC至9.3.0
    C# CefSharp 新版本(83 以后版本) 如何在js中直接调用c#类
    毕业设计——驾驶证理论考试系统的设计与实现 2022年1月2日20:35:14
    送餐机器人乐动雷达记录
    linux下拉取git代码
  • 原文地址:https://www.cnblogs.com/xiaoshiwang/p/9824439.html
Copyright © 2011-2022 走看看