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

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

  •  
  •   Rieouu · Jul 23, 2018 · 16702 views
    This topic created in 3034 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
    Rieouu
    OP
    Jul 23, 2018
    1
    要是有现成的轮子就更好了
    satgi
    satgi
    Jul 23, 2018
    2
    任何时候,只要获取到已经连接了的客户端就可以。
    Rieouu
    Rieouu
    OP
    Jul 23, 2018
    4
    @satgi 请问具体怎么做呢,我对 websocket 不怎么熟所以很迷惑,谢谢
    Rieouu
    Rieouu
    OP
    Jul 23, 2018
    5
    @ben1024 您这个的确符合我的要求,不过要是 Java 的就更好了,看来使用 websocket 肯定是可以实现的,谢谢
    qiushijie
    qiushijie
    Jul 23, 2018 via Android
    6
    用一个 map 把客户端链接保存,然后遍历去发送就行了
    Rieouu
    Rieouu
    OP
    Jul 23, 2018
    7
    @qiushijie 您说的这个发送是指调用某个方法吗,我就是在这里不明白怎么发送消息
    liuxu
    liuxu
    Jul 23, 2018
    8
    onMessage 更像一个路由,所有人连到 onMessage,让它来处理
    opengps
    opengps
    Jul 23, 2018
    10
    连接之后,谁都可以互相发送,你需要的是每个 websocket 有个 id 标识,长连接建立后,通过 id 识别,直接推送,前端就会收到
    satgi
    satgi
    Jul 23, 2018
    11
    ```
    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
    windfarer
    Jul 23, 2018
    12
    neoblackcap
    neoblackcap
    Jul 23, 2018
    13
    1.到底是 webscoket 还是 socket 这个要分清
    2.如 6L @qiushijie 所说,你先记录好每个连接到底是谁,然后分别对每个连接写你要推送的消息就好了
    mokeyjay
    mokeyjay
    Jul 23, 2018
    14
    用你的语言+空格+websocket 作为关键词组搜一下不就知道了
    Rieouu
    Rieouu
    OP
    Jul 23, 2018
    15
    @neoblackcap sorry 没说清楚哈,我要发送的消息是服务器通过 socket 接收的,是一个 TCP 消息,接收到消息后要把它显示到前端,所以用 websocket,看了各位大佬的回复,我还是先把 websocket 弄清楚,谢谢您
    aurelia
    aurelia
    Jul 23, 2018
    16
    多监听一个 tcp 或者 http 端口 后台有新数据 就请求 轮询 fd 或者直接在后台发送 ws 发送完就断掉也是可以的
    neoblackcap
    neoblackcap
    Jul 23, 2018
    17
    @Rieouu 你这样显然要求建立两组连接吧,一组 websocket,一组 socket,socket 收到数据,然后通过队列之类的方式,批量往 websocket 写入消息
    Rieouu
    Rieouu
    OP
    Jul 23, 2018
    18
    @neoblackcap 目前使用的是 netty 接收消息,本来想的是 netty 收到消息直接通过 websocket 推送,然后坐了半天没做出来,实验室项目老师催得紧所以在 v 站向大佬提问。。用消息队列会不会太麻烦了,毕竟以前没弄过
    Rieouu
    Rieouu
    OP
    Jul 23, 2018
    19
    @mokeyjay 搜到一大堆聊天室都不是我想要的,所以来 v 站寻求大佬帮助
    qinxi
    qinxi
    Jul 23, 2018
    20
    你消息怎么来的在这个场景中不重要.重要的是你现在需要往网页上推送,那就使用 websocket ,最基本的 百度都能搜出来.
    crist
    crist
    Jul 23, 2018
    21
    workerman 是可以的,swoole 就不知道了。
    satgi
    satgi
    Jul 23, 2018
    22
    @Rieouu
    看#11 代码,我把向客户端发消息的代码封装在 pushMessage 方法里,你什么时候想向客户端发消息,调用 pushMessage 就可以了。

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