• 请不要在回答技术问题时复制粘贴 AI 生成的内容
Rieouu
V2EX  ›  程序员

服务器怎么通过 websocket 主动向前端推送数据?向各位大佬请教

  •  
  •   Rieouu · Jul 23, 2018 · 16287 views
    This topic created in 2859 days ago, the information mentioned may be changed or developed.

    我的服务器通过 socket 接收到数据,请问怎么通过 websocket 实现后台有数据就推送到前台呢?看了 websocket 的例子,通过 onMessage 方法都是需要前台有消息请求才会触发这个方法,有没有主动的 write 方法直接写到前台呢,希望有做过这方面问题的大佬赐教

    63 replies    2019-03-20 18:58:01 +08:00
    Rieouu
        1
    Rieouu  
    OP
       Jul 23, 2018
    要是有现成的轮子就更好了
    satgi
        2
    satgi  
       Jul 23, 2018
    任何时候,只要获取到已经连接了的客户端就可以。
    ben1024
        3
    ben1024  
       Jul 23, 2018
    Rieouu
        4
    Rieouu  
    OP
       Jul 23, 2018
    @satgi 请问具体怎么做呢,我对 websocket 不怎么熟所以很迷惑,谢谢
    Rieouu
        5
    Rieouu  
    OP
       Jul 23, 2018
    @ben1024 您这个的确符合我的要求,不过要是 Java 的就更好了,看来使用 websocket 肯定是可以实现的,谢谢
    qiushijie
        6
    qiushijie  
       Jul 23, 2018 via Android
    用一个 map 把客户端链接保存,然后遍历去发送就行了
    Rieouu
        7
    Rieouu  
    OP
       Jul 23, 2018
    @qiushijie 您说的这个发送是指调用某个方法吗,我就是在这里不明白怎么发送消息
    liuxu
        8
    liuxu  
       Jul 23, 2018
    onMessage 更像一个路由,所有人连到 onMessage,让它来处理
    lsls931011
        9
    lsls931011  
       Jul 23, 2018
    opengps
        10
    opengps  
       Jul 23, 2018
    连接之后,谁都可以互相发送,你需要的是每个 websocket 有个 id 标识,长连接建立后,通过 id 识别,直接推送,前端就会收到
    satgi
        11
    satgi  
       Jul 23, 2018
    ```
    let clients = [];

    wss.on('connection', ws => {
    clients.push(ws);
    // onMessage
    ws.on('message', message => {
    pushMessage('message received');
    });
    });

    function pushMessage (message) {
    clients.forEach(client =>{
    client.send(message);
    });
    }

    // data received from socket, then push to clients
    let data = dataFromSocket;
    pushMessage(data);
    ```
    windfarer
        12
    windfarer  
       Jul 23, 2018
    neoblackcap
        13
    neoblackcap  
       Jul 23, 2018
    1.到底是 webscoket 还是 socket 这个要分清
    2.如 6L @qiushijie 所说,你先记录好每个连接到底是谁,然后分别对每个连接写你要推送的消息就好了
    mokeyjay
        14
    mokeyjay  
       Jul 23, 2018
    用你的语言+空格+websocket 作为关键词组搜一下不就知道了
    Rieouu
        15
    Rieouu  
    OP
       Jul 23, 2018
    @neoblackcap sorry 没说清楚哈,我要发送的消息是服务器通过 socket 接收的,是一个 TCP 消息,接收到消息后要把它显示到前端,所以用 websocket,看了各位大佬的回复,我还是先把 websocket 弄清楚,谢谢您
    aurelia
        16
    aurelia  
       Jul 23, 2018
    多监听一个 tcp 或者 http 端口 后台有新数据 就请求 轮询 fd 或者直接在后台发送 ws 发送完就断掉也是可以的
    neoblackcap
        17
    neoblackcap  
       Jul 23, 2018
    @Rieouu 你这样显然要求建立两组连接吧,一组 websocket,一组 socket,socket 收到数据,然后通过队列之类的方式,批量往 websocket 写入消息
    Rieouu
        18
    Rieouu  
    OP
       Jul 23, 2018
    @neoblackcap 目前使用的是 netty 接收消息,本来想的是 netty 收到消息直接通过 websocket 推送,然后坐了半天没做出来,实验室项目老师催得紧所以在 v 站向大佬提问。。用消息队列会不会太麻烦了,毕竟以前没弄过
    Rieouu
        19
    Rieouu  
    OP
       Jul 23, 2018
    @mokeyjay 搜到一大堆聊天室都不是我想要的,所以来 v 站寻求大佬帮助
    qinxi
        20
    qinxi  
       Jul 23, 2018
    你消息怎么来的在这个场景中不重要.重要的是你现在需要往网页上推送,那就使用 websocket ,最基本的 百度都能搜出来.
    crist
        21
    crist  
       Jul 23, 2018
    workerman 是可以的,swoole 就不知道了。
    satgi
        22
    satgi  
       Jul 23, 2018
    @Rieouu
    看#11 代码,我把向客户端发消息的代码封装在 pushMessage 方法里,你什么时候想向客户端发消息,调用 pushMessage 就可以了。

    这里的关键是 clients 变量,用来存储已经连接的客户端,只要你想发消息时候可以访问到 clients,就可以向里面的任意客户端发消息。
    qinxi
        23
    qinxi  
       Jul 23, 2018
    @Rieouu 能筛选出自己需要的东西应该是程序员最基本的技能吧.你说你想要轮胎,别人给你一辆汽车.你说不行,我只要轮胎
    xiaopenggggggg
        24
    xiaopenggggggg  
       Jul 23, 2018
    前端是是要订阅 websocket 推送的节点的
    myyou
        25
    myyou  
       Jul 23, 2018
    使用消息队列,每一个连接就启动一个线程,这个线程记录连接对象和订阅一个消息频道(消息频道名字写入缓存),持续监听这个消息频道,有消息就推送,服务端只需要向这个消息频道推送消息就行。
    Rieouu
        26
    Rieouu  
    OP
       Jul 23, 2018
    @qinxi 说的对,可能是自己不懂的东西就倾向于寻求帮助,bad coder
    Rieouu
        27
    Rieouu  
    OP
       Jul 23, 2018
    @myyou 你这个比较靠谱,我正在这方面努力
    Rieouu
        28
    Rieouu  
    OP
       Jul 23, 2018
    @satgi 谢谢哈,我正在研究大佬的代码呢
    cnit
        29
    cnit  
       Jul 23, 2018
    Rieouu
        30
    Rieouu  
    OP
       Jul 23, 2018
    @cnit 这个不错哦,谢谢
    wm5d8b
        31
    wm5d8b  
       Jul 23, 2018 via Android
    spring boot 官方不是有现成的例子嘛
    jswh
        32
    jswh  
       Jul 23, 2018
    socket io 了解一下
    sarices
        33
    sarices  
       Jul 23, 2018
    swoole 我是把服务器当成一个特别客户端,用客户端方式向服务器发送需要推送的消息,然后通过 onMessage 推送到其他客户端
    Rieouu
        34
    Rieouu  
    OP
       Jul 23, 2018
    @sarices 还可以这么做吗,服务器用作客户端,我来了解一下
    qiayue
        35
    qiayue  
    PRO
       Jul 23, 2018   ❤️ 1
    可以采用订阅机制
    假设你有温度和湿度两个数据,有 A、B 两个页面,A 只需要实时显示温度数据,B 需要实时显示温度和湿度两个数据
    浏览器打开 AB 页面后,主动连接到你的 websocket 服务,然后发送需要订阅的数据
    websocket 服务有一个 map 记录连接,以及对应的连接订阅了哪些数据
    你 netty 收到数据后,通过某种方式传给 websocket 服务(可以通过 http 传,也可以 socket 传,或者其他方式)
    websocket 服务每次收到 netty 传过来的一个数据,就从 map 中找出订阅了这个数据的所有连接,循环发送
    页面收到收据后,显示出来
    Rieouu
        36
    Rieouu  
    OP
       Jul 23, 2018
    @wm5d8b 看来要学习一下 springboot 了
    Rieouu
        37
    Rieouu  
    OP
       Jul 23, 2018
    @qiayue 有大佬建议把 netty 收到的消息放到消息队列,websocket 从消息队列读消息发布出去,跟你说的还是挺像的,我正在看着方面,谢谢你的回复~
    e8c47a0d
        38
    e8c47a0d  
       Jul 23, 2018
    socket.io 把,相当于是一个 WebSocket 的包装,相对自己写会方便很多,碰到不支持 websocket 的浏览器,socket.io 还能用长链接、pooling 模式。
    Rieouu
        39
    Rieouu  
    OP
       Jul 23, 2018
    @e8c47a0d 好的,都在看一下
    zrlhk
        40
    zrlhk  
       Jul 23, 2018
    workerman swoole 轮子多了去了
    Rieouu
        41
    Rieouu  
    OP
       Jul 23, 2018
    @zrlhk 主要我后台使用 Java 做的,Java 要是有类似 workman 的框架就好了
    zchlwj
        42
    zchlwj  
       Jul 23, 2018
    @Rieouu spring-boot websocket 现成的轮子
    inoki
        43
    inoki  
       Jul 23, 2018 via Android
    @crist swoole 有个 server 主动 push 的方法可以实现
    Rieouu
        44
    Rieouu  
    OP
       Jul 23, 2018
    @zchlwj 可以主动 push 吗,我读书少别骗我哈
    pipixia
        45
    pipixia  
       Jul 23, 2018 via Android
    记得 tomcat 有现成的 websocket 直接在 onMessage 里面遍历 session 发过去就行了
    Rieouu
        46
    Rieouu  
    OP
       Jul 23, 2018
    @pipixia onmessage 是需要前端发消息来触发这个方法,可是我的数据来自于服务器,不能直接调用 onmessage 发送吧
    tilv37
        47
    tilv37  
       Jul 23, 2018
    应该可以在服务端维护一个客户端的 map 啊,然后取出制定客户端的连接推消息就行了
    mary9
        48
    mary9  
       Jul 23, 2018   ❤️ 1
    用过 socket.io ,也研究过这个问题。socket.io 主动发送的话,有两个,一个是一开始客户端连接到服务器,然后有一个监听连接的事件,在这个连接事件中写你要的发送给客户端的东西。后面的话,只能是通过一个定时器了,我之前写的是 setInterval,定时向客户端发送需要的数据。不过这个方法需要在断开连接的时候清除掉你生成的 setInterval,不然 CPU 的内存会上升的。后面也没想到其他的方法,我再研究一下来补坑。
    limbo0
        49
    limbo0  
       Jul 23, 2018
    单端推送可以看看 sse
    xm0625
        50
    xm0625  
       Jul 23, 2018
    可以去看下我 BusHelper 项目 中间用到了 WebSocket 技术
    Rieouu
        51
    Rieouu  
    OP
       Jul 23, 2018
    @mary9 期待您研究的救国哦
    Rieouu
        52
    Rieouu  
    OP
       Jul 23, 2018
    @mary9 期待您研究的结果哈
    Rieouu
        53
    Rieouu  
    OP
       Jul 23, 2018
    @xm0625 去看大佬的项目~
    pipixia
        54
    pipixia  
       Jul 23, 2018 via Android
    @Rieouu 你总有地方放 session 吧 直接遍历他发送消息
    Rieouu
        55
    Rieouu  
    OP
       Jul 23, 2018
    @pipixia session 是放在一个容器对象里面的,我来试试看
    wdlth
        56
    wdlth  
       Jul 23, 2018
    把 Session 存起来,找到 Session 就发
    Rieouu
        57
    Rieouu  
    OP
       Jul 24, 2018
    @wdlth 大佬说的是对的,我按照这个试验了是可行的
    hosaos
        59
    hosaos  
       Jul 24, 2018
    netty socket io 包含了自动重连一些封装好的功能 可以看看
    Rieouu
        60
    Rieouu  
    OP
       Jul 24, 2018
    @hosaos 谢谢我看一下哈
    Rieouu
        61
    Rieouu  
    OP
       Jul 24, 2018
    @kba977 谢谢
    ynkkdev
        62
    ynkkdev  
       Mar 20, 2019
    大佬,你的问题最后是怎么解决的?我的需求和你几乎一样,也是有一个 socket 客户端,接收到消息以后需要利用 websocket 推送到 web 前端,只不过我是 py,可以说一下你最后的解决思路吗
    Rieouu
        63
    Rieouu  
    OP
       Mar 20, 2019
    @youngce 我的后台使用的是 springboot+springmvc,接收 socket 请求使用的是 netty,思路就是 netty 收到数据后对数据进行解析并包装成前端需要的 JSON 形式,然后通过 websocket 直接推送给所有的客户端,你只要在 websocket 保存每一个 websocket 连接,然后封装好相应的 push 推送方法,我当时是参考这个做的: https://www.cnblogs.com/xdp-gacl/p/5193279.html
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2556 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 105ms · UTC 16:00 · PVG 00:00 · LAX 09:00 · JFK 12:00
    ♥ Do have faith in what you're doing.