视频：

* for H5
  * [https://www.bilibili.com/video/BV1ck4y197BV/](https://www.bilibili.com/video/BV1ck4y197BV/)
  * [演示源码](https://gitee.com/noear/socket.d/tree/main/javascript/socketd-examples/demo01-js-ws)
* for UniAPP
  * [https://www.bilibili.com/video/BV1T94y1T7sp/](https://www.bilibili.com/video/BV1T94y1T7sp/)
  * [演示源码](https://gitee.com/noear/socket.d/tree/main/javascript/socketd-examples/demo03-uniapp-ws)



### 1、H5 演示地址：


<a href="/demo/demo01-js-ws/" target="_blank">/demo/demo01-js-ws/</a>

前端源码可以直接看网页源码（不太好看啊）。



### 2、配套服务端代码 - node.js：

包配置里添加依赖（package.json）

```json
{
  "name": "demo",
  "description": "socket.d for node.js demo",
  "author": "noear",
  "dependencies": {
    "@noear/socket.d": "2.5.20"
  }
}
```

代码（server.js）

```javascript
const {SocketD}  = require('@noear/socket.d');

function main(){
   let server = SocketD.createServer("sd:ws")
       .config(c=>c.port(8602).fragmentSize(1024 * 1024))
       .listen(buildListener())
       .start();
}

function buildListener() {
    return SocketD.newEventListener()
        .doOnOpen(s => {
            console.info("onOpen: " + s.sessionId());
        }).doOnMessage((s, m) => {
            console.info("onMessage: " + m);
        }).doOn("/demo", (s, m) => {
            if (m.isRequest()) {
                s.reply(m, SocketD.newEntity("me to! ref:" + m.dataAsString()));
            }

            if (m.isSubscribe()) {
                let size = m.rangeSize();
                for (let i = 1; i <= size; i++ ) {
                    s.reply(m, SocketD.newEntity("me to-" + i));
                }
                s.replyEnd(m, SocketD.newEntity("welcome to my home!"));
            }
        }).doOn("/upload", (s, m) => {
            if (m.isRequest()) {
                let fileName = m.meta(SocketD.EntityMetas.META_DATA_DISPOSITION_FILENAME);
                if (fileName) {
                    s.reply(m, SocketD.newEntity("file received: " + fileName + ", size: " + m.dataSize()));
                }else{
                    s.reply(m, SocketD.newEntity("no file! size: " + m.dataSize()));
                }
            }
        }).doOn("/download", (s, m) => {
            if (m.isRequest()) {
                let fileEntity = SocketD.newEntity("...");//todo://SocketD.newEntity(fs.readFileSync("/Users/noear/Movies/snack3-rce-poc.mov"));
                s.reply(m, fileEntity);
            }
        }).doOn("/push", (s, m) => {
            if (s.attrHas("push")) {
                return;
            }

            s.attrPut("push", "1");

            for (let i = 0; i++; i < 100) {
                if (s.attrHas("push") == false) {
                    break;
                }

                s.send("/push", SocketD.newEntity("push test"));
                //todo:sleep
            }
        }).doOn("/unpush", (s, m) => {
            s.attrMap().remove("push");
        })
        .doOnClose(s => {
            console.info("onClose: " + s.sessionId());
        }).doOnError((s, err) => {
            console.warn("onError: " + s.sessionId());
        });
}

main();
```