sendIP(type, data, options, index = null, autoConnect = true) {
    /** @type {IP} */
    let ip;
    let idx = index;
    if (IP.isIP(type)) {
      ip = /** @type {IP} */ (type);
      idx = ip.index;
    } else if (typeof type === 'string') {
      ip = new IP(type, data, options);
    } else {
      throw new Error('Unknown type for IP type');
    }
    const sockets = this.getSockets(idx);
    this.checkRequired(sockets);

    if (ip.datatype === 'all') {
      // Stamp non-specific IP objects with port datatype
      ip.datatype = this.getDataType();
    }
    if (this.getSchema() && !ip.schema) {
      // Stamp non-specific IP objects with port schema
      ip.schema = this.getSchema();
    }

    const cachedData = this.cache[`${idx}`] != null ? this.cache[`${idx}`].data : undefined;
    if (this.isCaching() && data !== cachedData) {
      this.cache[`${idx}`] = ip;
    }
    let pristine = true;
    sockets.forEach((socket) => {
      if (!socket) { return; }
      if (pristine) {
        socket.post(ip, autoConnect);
        pristine = false;
      } else {
        if (ip.clonable) { ip = ip.clone(); }
        socket.post(ip, autoConnect);
      }
    });
    return this;
  }
@param {string|IP} type
@param {any} [data]
@param {import("./IP").IPOptions} [options]
@param {number|null} [index]
@param {boolean} [autoConnect]