Go语言 websocket 一个端口建立多个连接会频繁断开

建立websocket连接的URL: var url = "ws://" + window.location.host + "/dev_ws?id=" + mac();

下面是Go语言的发送心跳消息的代码

func (d *Device) WSCheck() {
    //go func() { }() 以并发的方式调用匿名函数funcx
    go func() {
        for d.online {
            d.WebsocketSendString(fmt.Sprintf(`{"eventType":"sundyn_ws_check","time":"%s"}`,
                  time.Now().Format("2006-01-02 15:04:05")))
            time.Sleep(time.Second * 20)
        }
    }()
}

// 通过 WebSocket 发送字符串
func (d *Device) WebsocketSendString(str string) bool {
    if !d.online {
        return false
    }
    log.Println(d.ws.Request().RemoteAddr)
    if err := websocket.Message.Send(d.ws, str); err != nil {
        log.Println("设备", d.ws.Request().RemoteAddr,
            "[",d.ws.Request().Form.Get("id"),"] websocket 发送消息失败:%s", err)
        _ = d.ws.Close()
        return false
    }
    return true
}


本机(192.168.1.182)通过如下URL建立websocket连接的时候, 前端接收心跳正常(20秒一次),连接正常
URL: ws://192.168.1.182:27017/dev_ws?id=F460E249E981
image.png


本机(192.168.1.182)/本机和其他设备(192.168.1.108)  同一时段通过如下两个URL建立websocket连接的时候, 前端接收心跳正常(20秒一次),连接都正常
URL: ws://192.168.1.182:27017/dev_ws?id=F460E249E981
URL: ws://192.168.1.182:27017/dev_ws?id=ECA86B96E961


本机(192.168.1.182)和其他设备(192.168.1.108)  同一时段通过同一个URL建立websocket连接的时候
URL: ws://192.168.1.182:27017/dev_ws?id=F460E249E981
前端接收心跳频率变快
image
频繁重连(ip是108和182)
image.png

前端js重连机制

var timeoutId = "";
function sundyn_ws_check() {
    if(timeoutId != ""){
        clearTimeout(timeoutId);
    }
    timeoutId = setTimeout(function (){ 
        app.RetryConn();
    }, 30000);
}

我刚开始做这块, 我还不太懂, 我感觉可能是websocket.Message.Send(d.ws, str)的问题, 不同设备连接同一个URL会影响消息的发送,只会给后连接的发送心跳消息, 导致前一个接收不到心跳重连


有谁帮忙解答一下, 是哪出的问题及怎么解决
万分感谢!






需要更多代码往下看

js:

function main() {
    if (!window["WebSocket"]) {
        alert("您的浏览器不支持 WebSocket, 程序无法正常运行!!!");
        return
    }
    setmousedown();
    var url = "ws://" + window.location.host + "/dev_ws?id=" + mac();
    createWS(url);
}

//心跳重连
var timeoutId = "";
function sundyn_ws_check() {
    if(timeoutId != ""){
        clearTimeout(timeoutId);
    }
    timeoutId = setTimeout(function (){ 
        app.RetryConn();
    }, 30000);
}


function mac() {
    var s = window.location.toString();
    s = s.substr(s.indexOf("/devices/") + 9);
    s = s.substr(0, s.indexOf("/"));
    return s;
}

function createWS(url) {
    console.log("准备连接" + url);
    var socket = new WebSocket(url);

    socket.onclose = function () {
        console.log("连接被断开");
        app.RetryConn();
    };

    socket.onopen = function () {
        console.log("已连接");
        app.CaptureScr();
    };

    socket.onerror = function (e) {
        console.log("error:" + e);
    };

    socket.onmessage = function (e) {
        console.log("get json:" + e.data);
        var obj = eval('(' + e.data + ')');

        if (!("eventType" in obj)) {
            console.log("未找到 eventType, 该json格式不受支持");
            return
        }

        var s = obj.eventType;
        var jh = e.data + "";
        s = s + "('" + jh + "')";
        eval(s);
    };
}

main();



处理websocket连接的代码:

http.Handle("/dev_ws", websocket.Handler(DeviceRequestProc))


func DeviceRequestProc(ws *websocket.Conn) {
    defer ws.Close()
    defer ws.Request().Body.Close()
    _ = ws.Request().ParseForm()
    mac := ws.Request().Form.Get("id")
    log.Println("设备", ws.Request().RemoteAddr, "[", mac, "] websocket 连接建立")

    dev := devInfo.getDeviceByMac(mac)
    if dev == nil {
        _ = websocket.Message.Send(ws, "未找到对应设备配置")
        log.Println("设备", ws.Request().RemoteAddr, "[", mac, "] websocket 连接未找到对应设备")
        return
    }
    dev.online = true
    dev.ws = ws
    dev.WSCheck()

    reply := ""
    for {
        //此处阻塞,等待有数据可读
        err := websocket.Message.Receive(ws, &reply)
        if  err != nil {
            break
        }
        dev.ProcessWSMsg(reply)
    }
    dev.online = false
    dev.ws = nil
    log.Println("设备", ws.Request().RemoteAddr, "[",ws.Request().Form.Get("id"),"] websocket 连接断开")

}
阅读 6.1k
2 个回答

能多贴一些代码吗?

websocket发送消息要加锁,否则会crash

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题