# WebSocket 如何实现服务端向客户端发送消息？

- Link: https://www.ixiqin.com/2019/08/11/websocket-how-to-implement-the-server-to-the-client-sends-the-message/
- Published: 2019-08-11T08:50:42+08:00
- Author: 白宦成

文章目录

 [Toggle](https://www.ixiqin.com/2019/08/11/websocket-how-to-implement-the-server-to-the-client-sends-the-message/#)

 * [需求](https://www.ixiqin.com/2019/08/11/websocket-how-to-implement-the-server-to-the-client-sends-the-message/#%e9%9c%80%e6%b1%82)
 * [实现](https://www.ixiqin.com/2019/08/11/websocket-how-to-implement-the-server-to-the-client-sends-the-message/#%e5%ae%9e%e7%8e%b0)
 * [参考代码](https://www.ixiqin.com/2019/08/11/websocket-how-to-implement-the-server-to-the-client-sends-the-message/#%e5%8f%82%e8%80%83%e4%bb%a3%e7%a0%81)
    - [说明](https://www.ixiqin.com/2019/08/11/websocket-how-to-implement-the-server-to-the-client-sends-the-message/#%e8%af%b4%e6%98%8e)
    - [服务端代码](https://www.ixiqin.com/2019/08/11/websocket-how-to-implement-the-server-to-the-client-sends-the-message/#%e6%9c%8d%e5%8a%a1%e7%ab%af%e4%bb%a3%e7%a0%81)
 * [参考文章](https://www.ixiqin.com/2019/08/11/websocket-how-to-implement-the-server-to-the-client-sends-the-message/#%e5%8f%82%e8%80%83%e6%96%87%e7%ab%a0)

我们都知道， Websocket 是一个双向的通讯方式，一般情况下，我们都是根据 Client 的情况
返回信息，但是在一个更加健壮的系统，我们可能需要主动的向客户端发送消息。我试图在
中文网络去搜索，查找相关信息，无果。因此便开始搜索英文世界中的内容。如今已经实现
我想要的需求，便写一篇文章分享一下。

## 需求

![](https://postimg.aliavv.com/mbp/aurqs.jpeg)

需求是 Websocket 服务端作为中心控制服务器，会对外提供一个 RESTFul API，其他部件通过
RESTFul API 来链接 WebSocket 服务端发起请求，由 WebSocket 服务端进行设备相关的控制。

## 实现

首先，前提是我们的服务端和设备端是保持着 websocket 的长链接操作的，那么，我们在 
RESTFul 中只要获取到这个链接，就可以发送消息了。

而 websocket 中，我们如果想要获取到一个特定的链接，就需要使用 websocket 的 **socket.
id **来完成我们的需求。这就要求我们提前将 socket.id 存储起来，这样当我们需要的时候，
我们就可以直接拿 socket.id 来发送消息。

![](https://postimg.aliavv.com/mbp/3oyzs.jpeg)

在 Socket.io 中，你需要使用 _io.sockets.connected[socketID].emit(“greeting”, “Howdy,
User 1!”);_ 来发送消息。

在 egg.js 中，则是 _app.io.sockets.connected[socketID].emit(‘res’, ‘send From app’);_

有了这个代码，你就可以实现在 RESTFul API 中向 Client 中发送消息了。

## 参考代码

### 说明

本例中使用的是 Socket.io + Egg.js 实现的

### 服务端代码

    ```javascript
    //config/config.default.js
    config.io = {
        namespace: {
          '/': {
            connectionMiddleware: [ 'auth' ],
            packetMiddleware: [],
          },
        },
      };
    Code language: JavaScript (javascript)
    ```

    ```javascript
    // app/io/middleware/auth.js
    'use strict';
    module.exports = () => {
      return async (ctx, next) => {
        const { socket, app } = ctx;
        const id = socket.id; // 获取 Socket ID
        app.redis.set('pid', id); // 设置 Socket ID
        ctx.socket.emit('res', `Your id is ${id}`);
        await next();
      };
    };
    Code language: JavaScript (javascript)
    ```

    ```javascript
    // app/controller/home.js
    'use strict';
    const Controller = require('egg').Controller;
    class HomeController extends Controller {
      async send() {
        const { ctx, app } = this;
        const id = await app.redis.get('pid'); // 获取 ID
        app.io.sockets.connected[id].emit('res', 'send From app');// 发送数据
        ctx.body = 'ok';
      }
    }
    module.exports = HomeController;

    Code language: JavaScript (javascript)
    ```

## 参考文章

[https://michaelheap.com/sending-messages-to-certain-clients-with-socket-io/](https://michaelheap.com/sending-messages-to-certain-clients-with-socket-io/)
