很奇怪 wx.sendSocketMessage 在电脑版微信中,发送消息会报错?
发布于 5 年前 作者 juan56 4479 次浏览 来自 官方Issues

我发送的内容明明是 buffer 格式,发送的内容也没什么特别的。但是在电脑版的微信中 wx.onSocketError 却会报错:

createSocketTask: Browser sent a text frame containing invalid UTF-8

在开发工具,真机,平板均能正常收发消息,就PC版微信有问题。

可将下面代码直接复制到新建的项目中运行。

const app = getApp()

Page({
  data: {},
  onLoad: function () {
    var url = "wss://pml.dian3x.com";
    wx.connectSocket({ url: url });

    wx.onSocketOpen(function (res) {
      console.log("# open: " + url);

      // 这里发送握手包,服务端能正常收发
      var packet = Package.encode(Package.TYPE_HANDSHAKE, String.toUTF8Array(JSON.stringify(handshakeBuffer)));
      sendSocketMessage(packet.buffer);

      // 这里稍微延迟,等上面握手包发送完成后,握手成功后,下面发送的消息,服务端才会接收消息。
      setTimeout(function () {
        var route = "connector.StoryConfigHandler.getConfigInfo";
        var msg = {
          appGuid: "ef67dfc4-dec8-4ad2-9941-2861933615dc",
          sessionId: "e9cc5ddd-6a79-0e9f-7abd-4a8265b198da",
          version: "1.7.0"
        };

        // 在电脑版微信中,虽然下面 wx.sendSocketMessage 执行了 success 回调,但事实上服务端并没有收到任何内容。
        // 并且 wx.onSocketError 报错: createSocketTask: Browser sent a text frame containing invalid UTF-8
        // 这些代码是从项目中抽取整理出来的,在开发工具,真机,平板均能正常收发消息,就PC版微信有问题。
        sendMessage(route, msg);
      }, 2000);
    });

    wx.onSocketError(function (res) {
      console.error("---- wx.onSocketError ----");
      console.error(res);
    });

    wx.onSocketClose(function (res) {
      console.log("---- wx.onSocketClose ----");
      console.log(res);
    });

    wx.onSocketMessage(function (res) {
      console.log("---- wx.onSocketMessage ----");
      console.log(res);
    });
  },
});

// unicode string to utf8 byte
if (!String.toUTF8Array) {
  String.toUTF8Array = function (str) {
    var utf8 = [];
    for (var i = 0; i < str.length; i++) {
      var charcode = str.charCodeAt(i);
      if (charcode < 0x80) utf8.push(charcode);
      else if (charcode < 0x800) {
        utf8.push(0xc0 | (charcode >> 6),
          0x80 | (charcode & 0x3f));
      }
      else if (charcode < 0xd800 || charcode >= 0xe000) {
        utf8.push(0xe0 | (charcode >> 12),
          0x80 | ((charcode >> 6) & 0x3f),
          0x80 | (charcode & 0x3f));
      }
      // surrogate pair
      else {
        i++;
        // UTF-16 encodes 0x10000-0x10FFFF by
        // subtracting 0x10000 and splitting the
        // 20 bits of 0x0-0xFFFFF into two halves
        charcode = 0x10000 + (((charcode & 0x3ff) << 10)
          | (str.charCodeAt(i) & 0x3ff))
        utf8.push(0xf0 | (charcode >> 18),
          0x80 | ((charcode >> 12) & 0x3f),
          0x80 | ((charcode >> 6) & 0x3f),
          0x80 | (charcode & 0x3f));
      }
    }
    return utf8;
  };
}

// 
var JS_WS_CLIENT_TYPE = 'js-websocket';
var JS_WS_CLIENT_VERSION = '0.0.1';
var handshakeBuffer = {
  'sys': {
    type: JS_WS_CLIENT_TYPE,
    version: JS_WS_CLIENT_VERSION
  },
  'user': {
  }
};

// 
var Package = {};
Package.TYPE_HANDSHAKE = 1;
Package.TYPE_DATA = 4;
var PKG_HEAD_BYTES = 4;
var MSG_FLAG_BYTES = 1;
var MSG_ROUTE_LEN_BYTES = 1;
var MSG_ROUTE_CODE_MAX = 0xffff;
var ByteArray = Uint8Array; // Buffer

Package.encode = function (type, body) {
  var length = body ? body.length : 0;
  var buffer = new ByteArray(PKG_HEAD_BYTES + length);
  var index = 0;
  buffer[index++] = type & 0xff;
  buffer[index++] = (length >> 16) & 0xff;
  buffer[index++] = (length >> 8) & 0xff;
  buffer[index++] = length & 0xff;
  if (body) {
    copyArray(buffer, index, body, 0, length);
  }
  return buffer;
};

var copyArray = function (dest, doffset, src, soffset, length) {
  if ('function' === typeof src.copy) {
    // Buffer
    src.copy(dest, doffset, soffset, soffset + length);
  } else {
    // Uint8Array
    for (var index = 0; index < length; index++) {
      dest[doffset++] = src[soffset++];
    }
  }
};

var caculateMsgIdBytes = function (id) {
  var len = 0;
  do {
    len += 1;
    id >>= 7;
  } while (id > 0);
  return len;
};

var encodeMsgFlag = function (type, compressRoute, buffer, offset) {
  buffer[offset] = (type << 1) | 0;
  return offset + MSG_FLAG_BYTES;
};

var encodeMsgId = function (id, idBytes, buffer, offset) {
  var index = offset + idBytes - 1;
  buffer[index--] = id & 0x7f;
  while (index >= offset) {
    id >>= 7;
    buffer[index--] = id & 0x7f | 0x80;
  }
  return offset + idBytes;
};

var encodeMsgRoute = function (compressRoute, route, buffer, offset) {
  if (compressRoute) {
    if (route > MSG_ROUTE_CODE_MAX) {
      throw new Error('route number is overflow');
    }

    buffer[offset++] = (route >> 8) & 0xff;
    buffer[offset++] = route & 0xff;
  } else {
    if (route) {
      buffer[offset++] = route.length & 0xff;
      copyArray(buffer, offset, route, 0, route.length);
      offset += route.length;
    } else {
      buffer[offset++] = 0;
    }
  }
  return offset;
};

var encodeMsgBody = function (msg, buffer, offset) {
  copyArray(buffer, offset, msg, 0, msg.length);
  return offset + msg.length;
};

var Message = {};
Message.encode = function (id, type, compressRoute, route, msg) {
  // caculate message max length
  var idBytes = caculateMsgIdBytes(id);
  var msgLen = MSG_FLAG_BYTES + idBytes;
    msgLen += MSG_ROUTE_LEN_BYTES;
    if (route) {
      route = String.toUTF8Array(route);
      if (route.length > 255) {
        throw new Error('route maxlength is overflow');
      }
      msgLen += route.length;
    }

  if (msg) {
    msgLen += msg.length;
  }

  var buffer = new ByteArray(msgLen);
  var offset = 0;

  // add flag
  offset = encodeMsgFlag(type, compressRoute, buffer, offset);

  // add message id
  offset = encodeMsgId(id, idBytes, buffer, offset);

  // add route
  offset = encodeMsgRoute(compressRoute, route, buffer, offset);

  // add body
  offset = encodeMsgBody(msg, buffer, offset);

  return buffer;
};

var sendMessage = function (route, msg) {
  console.log("# " + route);
  console.log(msg);

  msg = String.toUTF8Array(JSON.stringify(msg));
  msg = Message.encode(1, 0, 0, route, msg);
  var packet = Package.encode(Package.TYPE_DATA, msg);
  // console.log(packet);

  sendSocketMessage(packet.buffer);
};

var sendSocketMessage = function (buffer) {
  wx.sendSocketMessage({
    data: buffer,
    success: function (res) { console.log("---- wx.sendSocketMessage successed ----"); },
    fail: function (res) {
      console.log("---- wx.sendSocketMessage failed ----");
      console.log(res);
    }
  });
};
1 回复
回到顶部