uni-app 支付宝云的Unicloud中使用websocket一直报异常"java.nio.channels.ClosedChannelException"

发布于 1周前 作者 yuanlaile 来自 Uni-App

uni-app 支付宝云的Unicloud中使用websocket一直报异常"java.nio.channels.ClosedChannelException"

示例代码:

module.exports = {  
    _before: function() { // 通用预处理器  

    },  
    _onWebsocketConnection: async function(event) {  
        console.log("onWebsocketConnection", event)  
    },  
    _onWebsocketMessage: async function(event) {  
        console.log("onWebsocketMessage", event)  
        const connectionId = event.connectionId;  
        const ws = uniCloud.webSocketServer()  
        await ws.close(connectionId)  
    },  
    _onWebsocketDisConnection: async function(event) {  
        console.log("onWebsocketDisConnection", event)  

    },  
    _onWebsocketError: async function(event) {  
        console.log("onWebsocketError", event)   
    },  
    getWsURL: async function() { // 获取websocket连接地址  
        console.log("getWsURL被调用")  
        const wsRequestParamsObj = {  
            hostIP: "192.1.1.1",  
            command: "1"  
        }  
        const ws = uniCloud.webSocketServer()  
        const hostURL = await ws.signedURL("web-socket-co", wsRequestParamsObj)  
        return hostURL  
    },  

}

操作步骤:

  1. 上传云对象
  2. 用apifox请求URL化的云对象的getWsURL获得ws的连接地址
  3. 用连接地址连接
  4. 发送一条消息

预期结果:

没有进入到_onWebsocketError事件中

实际结果:

进入了_onWebsocketError事件中,并且报错:“java.nio.channels.ClosedChannelException”

bug描述:

以下是我云对象的全部代码,非常规范的事件处理,但是每当连接上websocket服务后,发送一条消息,ws连接会断开,这个没问题. 但是为什么_onWebsocketError触发了?而且通过云对象的后台日志发现报"java.nio.channels.ClosedChannelException"这个错误?(具体请看第四张图) 我只连接ws,手动断开ws连接,观察后台日志就没有这个报错?这个是为什么?


5 回复

服务空间ID发一下。


回复 c***@163.com: 现在还会有这个问题吗?

方便的话私信我一下。

在uni-app结合支付宝云的Unicloud使用WebSocket时遇到java.nio.channels.ClosedChannelException异常,通常表明WebSocket连接在某个时刻被意外关闭了。这个异常可能由多种原因引起,包括客户端断开连接、服务器端主动关闭连接、网络问题或配置错误等。

为了解决这个问题,我们需要确保WebSocket连接的正确管理,包括连接的建立、数据传输和连接的关闭。下面是一个简化的示例,展示了如何在UniCloud云函数中管理WebSocket连接,同时处理可能的异常,包括ClosedChannelException

服务器端代码(UniCloud云函数)

// 引入必要的模块
const WebSocket = require('ws');
const server = new WebSocket.Server({ port: 8080 });

// 存储所有连接的客户端
const clients = new Set();

server.on('connection', (ws) => {
    clients.add(ws);
    console.log('New client connected');

    ws.on('message', (message) => {
        console.log(`Received message => ${message}`);
        // 广播消息给所有客户端
        clients.forEach((client) => {
            if (client.readyState === WebSocket.OPEN) {
                client.send(message);
            }
        });
    });

    ws.on('close', () => {
        clients.delete(ws);
        console.log('Client disconnected');
    });

    ws.on('error', (error) => {
        if (error instanceof WebSocket.errors.ClosedError) {
            console.error('WebSocket connection closed unexpectedly:', error);
        } else {
            console.error('WebSocket error:', error);
        }
        clients.delete(ws);
    });
});

console.log('WebSocket server is running on ws://localhost:8080');

客户端代码(uni-app)

const ws = uni.connectSocket({
    url: 'ws://your-server-address:8080',
});

ws.onMessage((res) => {
    console.log('Received:', res.data);
});

ws.onError((err) => {
    console.error('WebSocket error:', err);
    // 根据错误类型决定是否重连
    if (err.errMsg.includes('ClosedChannelException')) {
        // 处理特定异常,比如尝试重连
        console.error('Handling ClosedChannelException, attempting to reconnect...');
        // 重连逻辑...
    }
});

ws.onClose((res) => {
    console.log('WebSocket connection closed:', res);
    // 根据需要实现重连逻辑
});

// 发送消息
ws.send({
    data: 'Hello Server',
});

请注意,上述代码是简化的示例,用于说明如何在服务器端和客户端处理WebSocket连接。在实际应用中,你可能需要根据具体需求添加更多的错误处理和连接管理逻辑。同时,确保服务器端地址和端口配置正确,以及网络环境稳定。

回到顶部