linux下异步RPC的阶段性总结-非阻塞SOCKET客户端



  1. 尽可能使用非阻塞socket

    int flags, s;
        flags = fcntl (fd, F_GETFL, 0);  
          if (flags == -1){  
              close(fd);
              return -1;  
        }  
      
          flags |= O_NONBLOCK;  
          s = fcntl (fd, F_SETFL, flags);  
          if (s == -1){  
              close(fd);
              return -1;  
        }  

  2. 使用效率高效的epoll机制获取多个socket上的IN/OUT事件

  3. 非阻塞socket连接服务端时,不一定立即连接得上服务器

    通过判断connect函数的返回值和错误号做进一步跟踪

    int ret = ::connect(this->fd, (struct sockaddr*)&(server_addr), sizeof(server_addr));
                if(ret == 0){
                    this->on_connected();
                }else if(ret < 0 && errno != EINPROGRESS){
                    //error
                }else{
                    on_connecting();
                }

    1. IN/OUT事件时如果是connecting需要判断socket状态,socket reset发生时也会产生事件,然后才进入有效的读写

      if(this->connect_status == 1){//connecting
              int status = 0;
              socklen_t slen;
              if(getsockopt(this->fd, SOL_SOCKET, SO_ERROR, (void*)&status, &slen) < 0){
                  this->on_epollhup();
                  return;
              }
              if(status != 0){
                  this->on_epollhup();
                  return;
              }
             
              on_connected();
          }

  4. 读写发生错误时,通过错误码判断是错误还是数据读完或者缓冲区满了,发生错误则按socket断开处理

    错误代码包括:SIGPIP, EAGAIN 等, EAGAIN表示读完或者缓冲区满,等待下一次事件处理读或者写

  5. 为了达到更高的性能,epoll使用EPOLLET(边沿触发)机制,但是如果事件发生时,无数据可写时,下一次有数据时

    则不会发生OUT事件,因此可以记录一个写空转标识write_nil_loop,epoll_wait事件之前判断是否有数据发送并且发生write_nil_loop,如果有,则重新登记epoll事件

                if(worker->is_write_nil_loop() && (events & EPOLLOUT)){
                        epoll->remove(worker);
                        epoll->add(worker, events);
                    }else if(worker->get_events_mask() != events){
                        epoll->modify(worker, events);
                    }

       同时,读取数据时,尽可能将数据读完,直到recv返回值-1,errno== EAGAIN,其他错误按照出错处理



FROM:  http://my.oschina.net/aruan/blog/509896?p={{currentPage-1}}

  1. 尽可能使用非阻塞socket

    int flags, s;
        flags = fcntl (fd, F_GETFL, 0);  
          if (flags == -1){  
              close(fd);
              return -1;  
        }  
      
          flags |= O_NONBLOCK;  
          s = fcntl (fd, F_SETFL, flags);  
          if (s == -1){  
              close(fd);
              return -1;  
        }  

  2. 使用效率高效的epoll机制获取多个socket上的IN/OUT事件

  3. 非阻塞socket连接服务端时,不一定立即连接得上服务器

    通过判断connect函数的返回值和错误号做进一步跟踪

    int ret = ::connect(this->fd, (struct sockaddr*)&(server_addr), sizeof(server_addr));
                if(ret == 0){
                    this->on_connected();
                }else if(ret < 0 && errno != EINPROGRESS){
                    //error
                }else{
                    on_connecting();
                }

    1. IN/OUT事件时如果是connecting需要判断socket状态,socket reset发生时也会产生事件,然后才进入有效的读写

      if(this->connect_status == 1){//connecting
              int status = 0;
              socklen_t slen;
              if(getsockopt(this->fd, SOL_SOCKET, SO_ERROR, (void*)&status, &slen) < 0){
                  this->on_epollhup();
                  return;
              }
              if(status != 0){
                  this->on_epollhup();
                  return;
              }
             
              on_connected();
          }

  4. 读写发生错误时,通过错误码判断是错误还是数据读完或者缓冲区满了,发生错误则按socket断开处理

    错误代码包括:SIGPIP, EAGAIN 等, EAGAIN表示读完或者缓冲区满,等待下一次事件处理读或者写

  5. 为了达到更高的性能,epoll使用EPOLLET(边沿触发)机制,但是如果事件发生时,无数据可写时,下一次有数据时

    则不会发生OUT事件,因此可以记录一个写空转标识write_nil_loop,epoll_wait事件之前判断是否有数据发送并且发生write_nil_loop,如果有,则重新登记epoll事件

                if(worker->is_write_nil_loop() && (events & EPOLLOUT)){
                        epoll->remove(worker);
                        epoll->add(worker, events);
                    }else if(worker->get_events_mask() != events){
                        epoll->modify(worker, events);
                    }

       同时,读取数据时,尽可能将数据读完,直到recv返回值-1,errno== EAGAIN,其他错误按照出错处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值