public String binarySubLInteractorAtHostPort(String base64SubLRequest, String hostname, String port) {
    int timeoutCount = 0;
    Base64 base64 = new Base64();
    while (true) {
      try {
        CycAccess cycAccess = establishAndVerifyCycAccess(hostname, port);        
        CycList subLRequest = (CycList) base64.decodeCycObject(base64SubLRequest, 0);
        subLRequest = unescape(subLRequest);
        Log.current.println("subLRequest " + subLRequest.toString() + "\n");
        Object response = null;
        try {
          response = cycAccess.converseObject(subLRequest);
        }
        catch (Exception e) {
          Log.current.println("CycApiException " + e.getMessage());
          if (e.getMessage().equals("Connection timed out") && 
            (++timeoutCount < MAX_CONNECTION_TIMEOUTS)) {
            Log.current.println("Connection timeout handled for " + cycAccess);
            Log.current.println("Retry attempt " + timeoutCount);
            cycAccess.close();
            cycAccess = null;
            continue;
          }
          CycList exception = new CycList();
          exception.add(CycObjectFactory.makeCycSymbol("CycApiException"));
          exception.add(e.getMessage());
          return base64.encodeCycObject(exception, 0);
        }
        return base64.encodeCycObject(response, 0);
      }
      catch (Exception e) {
        Log.current.println("Exception " + e.getMessage());
        try {
          CycList exception = new CycList();
          exception.add(CycObjectFactory.makeCycSymbol("CycApiException"));
          exception.add(e.getMessage() + "\n" + StringUtils.getStringForException(e));
          return base64.encodeCycObject(exception, 0);
        }
        catch (Exception e1) {
        }
        return null;
      }
    }
  }