Socket.D v2.5.12

演示视频

</> markdown

视频:

1、H5 演示地址:

/demo/demo01-js-ws/

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

2、配套服务端代码 - java:

  • 添加依赖
<dependency>
    <groupId>org.noear</groupId>
    <artifactId>socketd-transport-java-websocket</artifactId>
    <version>2.5.12</version>
</dependency>
  • 代码
public class ServerTest {
    /**
     * 启动服务,给别的客户端调试
     */
    public static void main(String[] args) throws Exception {
        Server server = SocketD.createServer("sd:ws")
                .config(c -> c.port(8602).fragmentSize(1024 * 1024))
                .listen(buildListener())
                .start();

        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            RunUtils.runAndTry(server::stop);
        }));
    }

    /**
     * 构建监听器
     */
    private static Listener buildListener() {
        return new EventListener()
                .doOnOpen(s -> {
                    System.out.println("onOpen: " + s.sessionId() + ", meta=" + s.handshake().paramMap());
                }).doOnMessage((s, m) -> {
                    System.out.println("onMessage: " + m);
                }).doOn("/demo", (s, m) -> {
                    if (m.isRequest()) {
                        s.reply(m, new StringEntity("me to! ref:" + m.dataAsString()));
                    }

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

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

                    while (true) {
                        if (s.attrHas("push") == false) {
                            break;
                        }

                        s.send("/push", new StringEntity("push test"));
                        RunUtils.runAndTry(() -> Thread.sleep(200));
                    }
                }).doOn("/unpush", (s, m) -> {
                    s.attrMap().remove("push");
                })
                .doOnClose(s -> {
                    System.out.println("onClose: " + s.sessionId());
                }).doOnError((s, err) -> {
                    System.out.println("onError: " + s.sessionId());
                    err.printStackTrace();
                });
    }
}

3、配套服务端代码 - node.js:

包配置里添加依赖(package.json)

{
  "name": "demo",
  "description": "socket.d for node.js demo",
  "author": "noear",
  "dependencies": {
    "@noear/socket.d": "2.3.9",
    "ws": "^8.16.0"
  }
}

代码(index.js)

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!"));
            }

            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("no file! size: " + m.dataSize()));
                } else {
                    s.reply(m, SocketD.newEntity("file received: " + fileName + ", 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();