站点图标 起风网

autojs WebSocket

WebSocket是一种网络传输协议,可在单个TCP连接上进行全双工通信。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输。

在正常情况中,每个WebSocket都会经历一系列状态(生命周期事件):

在异常情况下,WebSocket可能由于HTTP升级问题、连接问题或任一端异常关闭,此时WebSocket会进入canceled状态:

请注意,每个端的状态过程都是独立的。到达正常关闭状态表示它已发送其所有传出消息并接收其所有传入消息,但不保证其他对端将成功接收其所有传入消息。

在Auto.js Pro中,我们通过$web.newWebSocket()来创建WebSocket并监听上述生命周期事件。

let ws = $web.newWebSocket("wss://echo.websocket.org", {
    eventThread: 'this'
});
ws.on("open", (res, ws) => {
    log("WebSocket已打开");
}).on("failure", (err, res, ws) => {
    log("WebSocket连接失败或中断");
    console.error(err);
}).on("closing", (code, reason, ws) => {
    log("WebSocket关闭中");
}).on("closed", (code, reason, ws) => {
    log("WebSocket已关闭: code = %d, reason = %s", code, reason);
});

#$web.newWebSocket(url[, options])

创建一个WebSocket对象并返回。使用这个对象来监听WebSocket生命周期事件,或发送文本、二进制消息。

#WebSocket

$web.newWebSocket返回的对象。

需要注意的是,在Pro 9.0.10以前,WebSocket不会在脚本退出时自动关闭或取消,因此建议在这之前的版本监听exit事件自动取消。参见WebSocket.cancel()

#WebSocket.send(text)

尝试将text加入消息队列以使用UTF-8编码作为文本数据发送。

如果消息成功加入队列,则此方法返回true。若消息缓冲区(16MB)已满,则此消息将被拒绝并触发WebSocket的正常关闭(也即关闭时会发送完当前队列中所有消息)。在这种情况下,此方法返回 false。

若此WebSocket处于已关闭、关闭中、已取消的任何其他情况下,也会返回false

此方法不会等待消息最终发送才返回,而是立即返回。

let ws = $web.newWebSocket("wss://echo.websocket.org", {
    eventThread: 'this'
});

ws.on("text", (text, ws) => {
    console.info("接收到文本消息: ", text);
});

console.log(ws.send('Hello, Auto.js Pro')); // 返回true

ws.close(1000, null);

console.log(ws.send('GoodBye')); // 返回false

#WebSocket.send(bytes)

尝试将bytes加入消息队列以作为二进制数据发送。

如果消息成功加入队列,则此方法返回true。若消息缓冲区(16MB)已满,则此消息将被拒绝并触发WebSocket的正常关闭(也即关闭时会发送完当前队列中所有消息)。在这种情况下,此方法返回 false。

若此WebSocket处于已关闭、关闭中、已取消的任何其他情况下,也会返回false

此方法不会等待消息最终发送才返回,而是立即返回。

要创建一个二进制消息,需要使用OkHttp的API,比如:

let ByteString = Packages.okio.ByteString;

let ws = $web.newWebSocket("wss://echo.websocket.org", {
    eventThread: 'this'
});

ws.on("text", (text, ws) => {
    console.info("接收到文本消息: ", text);
}).on("binary", (bytes, ws) => {
    console.info("收到二进制消息:大小 ", bytes.size());
    console.info("hex: ", bytes.hex());
    console.info("base64: ", bytes.base64());
    console.info("md5: ", bytes.md5());
    console.info("bytes: ", bytes.toByteArray());
});

ws.send(ByteString.of($files.readBytes('./test.png'))); // 从byte\[\]创建二进制数据并发送
ws.send(ByteString.encodeUtf8('你好')); // 将字符串按UTF8编码并创建二进制数据并发送
ws.send(ByteString.decodeBase64('QXV0by5qcyBQcm8geXlkcw==')); // 解码Base64并创建二进制数据并发送
ws.send(ByteString.decodeHex('621172314F60')); // 解码hex并创建二进制数据并发送

ws.close(1000, null);

更多ByteString的信息参见ByteString.javaopen in new window

#WebSocket.cancel()

立即关闭WebSocket持有的资源,丢弃整个消息队列的消息。若WebSocket已关闭或已取消,则不会执行任何操作。

let ws = $web.newWebSocket("wss://echo.websocket.org", {
    eventThread: 'this'
});

// 脚本退出时取消WebSocket
events.on('exit', () => {
    ws.cancel();
});

#WebSocket.close(code, reason)

尝试正常关闭此WebSocket。调用此函数后,将拒绝所有的send操作并返回false,也即不再接受新的消息;但调用函数是已经在队列中的的消息将继续传输。

若指定的code不在有效范围或者reason字符串过长,则抛出IllegalArgumentException

若WebSocket处于关闭中、已关闭、已取消状态,则返回false;否则返回true

let ws = $web.newWebSocket("wss://echo.websocket.org", {
    eventThread: 'this'
});

setTimeout(() => {
    ws.close(1000, null);
}, 5000);

#

退出移动版