boolean doTCPCheckMember(ID suspectMember, int port,
      boolean retryIfConnectFails) {
    Socket clientSocket = null;
    // make sure we try to check on the member for the contracted memberTimeout period
    // in case a timed socket.connect() returns immediately. Use milliseconds to be in
    // sync with the socket timeout parameter unit of measure
    long giveupTime = System.currentTimeMillis() + services.getConfig().getMemberTimeout();
    boolean passed = false;
    int iteration = 0;
    do {
      iteration++;
      if (iteration > 1) {
        try {
          Thread.sleep(100);
        } catch (InterruptedException e) {
          Thread.currentThread().interrupt();
          return false;
        }
      }
      try {
        logger.debug("Checking member {} with TCP socket connection {}:{}.", suspectMember,
            suspectMember.getInetAddress(), port);
        clientSocket =
            socketCreator.forAdvancedUse()
                .connect(new HostAndPort(suspectMember.getHostName(), port), (int) memberTimeout,
                    new ConnectTimeoutTask(services.getTimer(), memberTimeout), false, -1, false);
        clientSocket.setTcpNoDelay(true);
        passed = doTCPCheckMember(suspectMember, clientSocket);
      } catch (IOException e) {
        // this is expected if it is a connection-timeout or other failure
        // to connect
      } catch (IllegalStateException e) {
        // This is expected if ConnectTimeoutTask is scheduled on a timer that was already
        // cancelled.
        // Once a timer has been terminated, no more tasks may be scheduled on it.
        if (!isStopping) {
          logger.trace("Unexpected exception", e);
        }
      } finally {
        try {
          if (clientSocket != null) {
            clientSocket.setSoLinger(true, 0); // abort the connection
            clientSocket.close();
          }
        } catch (IOException e) {
          // expected
        }
      }
    } while (retryIfConnectFails && !passed && !isShutdown()
        && System.currentTimeMillis() < giveupTime);
    return passed;
  }
During final check, establish TCP connection between current member and suspect member. And
exchange PING/PONG message to see if the suspect member is still alive.

@param suspectMember member that does not respond to HeartbeatRequestMessage
@return true if successfully exchanged PING/PONG with TCP connection, otherwise false.
geode-membership/src/main/java/org/apache/geode/distributed/internal/membership/gms/fd/GMSHealthMonitor.java