private void closeSocket(Socket socket) {
   try {
     if (socket != null) {
       socket.close();
     }
   } catch (Exception e) {
     logger.error(e.getMessage(), e);
   }
 }
  @Override
  public void sendNotification(PushNotification notification) {
    byte[] plBytes = null;
    String payload = notification.getPayload().toString();
    try {
      plBytes = payload.getBytes(CHARSET_ENCODING);
      if (plBytes.length > PAY_LOAD_MAX_LENGTH) {
        logger.error("Payload execeed limit, the maximum size allowed is 256 bytes. " + payload);
        return;
      }
    } catch (UnsupportedEncodingException e) {
      logger.error(e.getMessage(), e);
      return;
    }

    /**
     * EN: If error happened before, just wait until the resending work finishes by another thread
     * and close the current socket CN: 如果发现当前连接有error-response,加锁等待,直到另外一个线程把重发做完后再继续发送
     */
    synchronized (lock) {
      if (errorHappendedLastConn) {
        closeSocket(socket);
        socket = null;
      }
      byte[] data = notification.generateData(plBytes);
      boolean isSuccessful = false;
      int retries = 0;
      while (retries < maxRetries) {
        try {
          boolean exceedIntervalTime =
              lastSuccessfulTime > 0
                  && (System.currentTimeMillis() - lastSuccessfulTime) > intervalTime;
          if (exceedIntervalTime) {
            closeSocket(socket);
            socket = null;
          }

          if (socket == null || socket.isClosed()) {
            socket = createNewSocket();
          }

          OutputStream socketOs = socket.getOutputStream();
          socketOs.write(data);
          socketOs.flush();
          isSuccessful = true;
          break;
        } catch (Exception e) {
          logger.error(connName + " " + e.getMessage(), e);
          closeSocket(socket);
          socket = null;
        }
        retries++;
      }
      if (!isSuccessful) {
        logger.error(String.format("%s Notification send failed. %s", connName, notification));
        return;
      } else {
        logger.info(
            String.format(
                "%s Send success. count: %s, notificaion: %s",
                connName, notificaionSentCount.incrementAndGet(), notification));

        notificationCachedQueue.add(notification);
        lastSuccessfulTime = System.currentTimeMillis();

        if (notificationCachedQueue.size() > maxCacheLength) {
          notificationCachedQueue.poll();
        }
      }
    }

    if (isFirstWrite) {
      isFirstWrite = false;
      /**
       * EN: When we create a socket, just a TCP/IP connection created. After we wrote data to the
       * stream, the SSL connection had been created. Now, it's time to read data from InputStream
       * CN: createSocket时只建立了TCP连接,还没有进行SSL认证,第一次写完数据后才真正完成认证。所以此时才开始 监听InputStream
       */
      startErrorWorker();
    }
  }