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

眉间皱痕 提交于 2020-04-10 18:36:11
  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,其他错误按照出错处理














易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!