zoukankan      html  css  js  c++  java
  • c/c++ linux epoll系列2 利用epoll_wait查看是否可以送信

    linux epoll系列2 利用epoll_wait查看是否可以送信

    write函数本来是非阻塞函数,但是当缓存区被写满后,再往缓存区里写的时候,就必须等待缓存区再次变成可写,所以这是write就变成了阻塞了,这个进程或者线程就堵住了,不能被响应了。

    epoll_wait函数可以判断出,缓存区是否可写,可写后再调用write函数,这样就避免了write函数被阻塞。

    例子1,是接收端。

    例子2, 是会发生阻塞的发送端。

    例子3,利用了epoll_wait,所以是不会发生阻塞的。

    例子1,接收端

    #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 sock0;
      sockaddr_in addr;
      sockaddr_in client;
      socklen_t len;
      int sock;
      int n;
      char buf[65536];
      int i;
    
      sock0 = socket(AF_INET, SOCK_STREAM, 0);
    
      addr.sin_family = AF_INET;
      addr.sin_port = htons(12345);
      addr.sin_addr.s_addr = INADDR_ANY;
      bind(sock0, (sockaddr*)&addr, sizeof(addr));
    
      listen(sock0, 5);
    
      len = sizeof(client);
      sock = accept(sock0, (sockaddr*)&client, &len);
    
      printf("after accept
    ");
    
      for(i = 0; i < 10; ++i){
        sleep(2);
        n = read(sock, buf, sizeof(buf));
        printf("recv data size:[%d] bytes
    ", n);
      }
    
      printf("close socket and finish
    ");
    
      close(sock);
    
      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(){
      sockaddr_in server;
      int sock;
      char buf[65536];
      int n;
    
      sock = socket(AF_INET, SOCK_STREAM, 0);
    
      server.sin_family = AF_INET;
      server.sin_port = htons(12345);
    
      inet_pton(AF_INET, "127.0.0.1", &server.sin_addr.s_addr);
    
      n = connect(sock, (sockaddr*)&server, sizeof(server));
      if(n != 0){
        perror("connect");
        return 1;
      }
    
      int cnt = 0;
      while(1){
        ++cnt;
        printf("[%d]write %ld bytes
    ", cnt, sizeof(buf));
        n = write(sock, buf, sizeof(buf));
        if(n <= 0){
          printf("write error:%d
    ", n);
          break;
        }
      }
    
      close(sock);
    
      return 0;
      
    }
    
    

    github源代码

    例子3,利用了epoll_wait,所以是不会发生阻塞的。

    #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(){
      sockaddr_in server;
      epoll_event ev, ev_ret[EVENTS];
      int sock, epfd;
      char buf[65536];
      int nfds;
      int n;
    
      sock = socket(AF_INET, SOCK_STREAM, 0);
    
      server.sin_family = AF_INET;
      server.sin_port = htons(12345);
    
      inet_pton(AF_INET, "127.0.0.1", &server.sin_addr.s_addr);
    
      n = connect(sock, (sockaddr*)&server, sizeof(server));
      if(n != 0){
        perror("connect");
        return 1;
      }
    
      epfd = epoll_create(2);
      if(epfd < 0){
        perror("epfd");
        return 1;
      }
    
      memset(&ev, 0, sizeof(ev));
      ev.events = EPOLLOUT;//可写
      ev.data.fd = sock;
      if(epoll_ctl(epfd, EPOLL_CTL_ADD, sock, &ev) != 0){
        perror("epoll_clt");
        return 1;
      }
    
      int cnt = 0;
      while(1){
        cnt++;
        printf("before epoll wait
    ");
    
        nfds = epoll_wait(epfd, ev_ret, EVENTS, -1);
        if(nfds < 0){
          perror("epoll_wait");
          return 1;
        }
    
        printf("after epoll_wait
    ");
    
        if(ev_ret[0].data.fd == sock){
          printf("[%d]write %ld types
    ", cnt, sizeof(buf));
    
          n = write(sock, buf, sizeof(buf));
          if(n <= 0){
    	printf("write error:%d
    ", n);
    	break;
          }
        }
      }
    
      close(sock);
      return 0;
    }
    

    github源代码

    运行方法:先运行接收端,再运行阻塞发送端。

    从运行结果可以看出:阻塞的发送端,缓存区溢出后,write函数变成阻塞的了。

    运行方法:先运行接收端,再运行非阻塞发送端。

    从运行结果可以看出:非阻塞的发送端,缓存区溢出后,write函数是没有被调用的。

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

    本人微信:xiaoshitou5854

  • 相关阅读:
    2013年3月1日星期五
    2013年2月26日星期二本地图片预览
    2013年3月2日星期六
    2013年第10周三低潮
    2013年第9周日见同学
    header发送Cookie
    HTTP Cookie header 中setcookie格式
    多台服务器共享session问题
    PHP中header头设置Cookie与内置setCookie的区别
    session原理及实现共享
  • 原文地址:https://www.cnblogs.com/xiaoshiwang/p/9824807.html
Copyright © 2011-2022 走看看