linux中send函數MSG_NOSIGNAL

linux下當連接斷開,還發數據的時候,不僅send()的返回值會有反映,而且還會向系統發送一個異常消息,如果不作處理,系統會出BrokePipe,程序會退出,這對於服務器提供穩定的服務將造成巨大的災難。爲此,send()函數的最後一個參數可以設MSG_NOSIGNAL,禁止send()函數向系統發送異常消息

//中間的select就是爲了偵測斷開後再次連接並二次send

int socket_send(async_socket_t* async_sock, uint8_t* buf, int len){
  uint8_t* ptr = buf;
  int left = len;
  int rc;
  while (left > 0) {
#ifdef __IOS__
    rc = send(async_sock->fd, ptr, left, 0);
#else
    rc = send(async_sock->fd, ptr, left, MSG_NOSIGNAL);
#endif


    if(rc>0){
      left -= rc;
      ptr += rc;
    }else if (rc<0) {
      if (errno == EAGAIN) {
        break;
      } else if (errno == EINTR) {
        continue;
      } else {
        printf("send step 1 failed\n");
        return -1;
      }
    }
  }

  if(left>0){
    printf("wait writeable");
    fd_set writeset;
    FD_ZERO(&writeset);
    int max_fd = async_sock->fd + 1;
    struct timeval timeout;
    while(!async_sock->bstop && left>0){      
      timeout.tv_sec = 0;
      timeout.tv_usec = 100*1000;
      FD_SET(async_sock->fd, &writeset);
      int ret = select(max_fd, NULL, &writeset, NULL, &timeout);
      if( ret == 0){//TIMEOUT
        continue;
      }else if( ret < 0){
        printf("select failed\n");
        if(errno == EINTR){
          continue;
        }
        return -1;
      }
      //writeable
#ifdef __IOS__
      rc = send(async_sock->fd, ptr, left, 0);
#else
      rc = send(async_sock->fd, ptr, left, MSG_NOSIGNAL);
#endif

      if(rc>0){
        left -= rc;
        ptr += rc;
      }else if (rc<0) {
        printf("send step 2 failed\n");
        return -1;
      }
    }

  }
  return len-left;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章