Socket.D
是基於"事件"和"語義消息""流"的網絡應用層傳輸協議。有用戶說,“Socket.D 之於 Socket,尤如 Vue 之於 Js、Mvc 之於 Http”。支持 tcp, udp, ws, kcp 傳輸。協議特點可參考《官網介紹》。
pyton 已開發完成,再在測試中;go, rust, c++ 正在開發中。
for Java 適配框架更新說明:
- 添加 CLOSE28_OPEN_FAIL 關閉碼,優化關閉處理
- 調整 SocketD.createXxx 的異常提示,帶上協議架構信息
- 調整 PathListener::of 更名爲 doOf,並添加 of 函數(應用不同)
for JavaScript 適配框架更新說明:
- 完成 for Node.js server 實現!!!
- 添加 Session::remoteAddress,localAddress 方法
- 添加 CLOSE28_OPEN_FAIL 關閉碼,優化關閉處理
- 調整 SocketD.createXxx 的異常提示,帶上協議架構信息
- 調整 PathListener::of 更名爲 doOf,並添加 of 函數(應用不同)
新增的接口體驗(for Node.js Server):
現在服務端可以用 java 也可以用 node.js(很快也可以用 python 了) 。for Node.js Server Demo:
- 包配置
{
"name": "demo",
"description": "socket.d for node.js demo",
"author": "noear",
"dependencies": {
"@noear/socket.d": "2.3.9",
"ws": "^8.16.0"
}
}
- 服務端示例代碼
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();
Socket.D.js 客戶能力演示:
- 監聽(相當於 ws 的增強)
多了事件路由。可以用一個連接,監聽不同的業務事件(類似於 http path)。
//打開客戶端會話(用 url 形式打開)
let session = await SocketD.createClient("sd:ws://127.0.0.1:8602/?token=1b0VsGusEkddgr3d")
.listen(SocketD.newEventListener()
.doOnOpen(s -> { //會話打開時
//...
}).doOnMessage((s, m) -> { //收到任意消息時
//打印
console.info(m);
}).doOn("/demo", (s, m) -> { //收到"/demo"事件的消息時
if (m.isRequest() || m.isSubscribe()) {
//答覆
s.replyEnd(m, SocketD.newEntity("And you too."));
}
}))
.open();
- 發送 和 發送文件(並獲取進度)
發送相對於 ws 多了元信息。可爲數據添加額外的業務標註。發送大數據時,會自動分片(接收端自動聚合)
//發送
session.send("/demo/hello", SocketD.newEntity("hi").metaPut("sender","noear"));
//發送文件,且獲取發送進度(如果有大數據發送,又需要顯示進度)//實際開發,要用 sendAndRequest 接口(以獲取接收確認)
session.send("/demo/upload", SocketD.newEntity(file)).thenProgress((isSend, val, max)=>{
if(isSend){
//獲取發送進度
console.info(`...${val}/${max}`);
}
});
- 請求 和 下載文件(或大數據塊)
這個相當於 ws 有了 ajax 的交互方式
//發送並請求(有點像 ajax)
let reply = session.sendAndRequest("/demo/hello", SocketD.newEntity()).thenReply(reply=>{
console.info(reply.dataAsString());
});
//發送並請求,且取接收進度(如果有大數據獲取,又需要顯示進度)
session.sendAndRequest("/demo/download", SocketD.newEntity()).thenProgress((isSend, val, max)=>{
if(!isSend){
//獲取接收進度
console.info(`...${val}/${max}`);
}
}).thenReply(reply=>{
//reply.data()...
}).thenError(err=>{
//如果有出錯?
});
- 訂閱 與 流量控制(一般用於流加載)
通過 range(start, size) 指定數據範圍,由 sendAndSubscribe 發起訂閱,通過 thenReply 多次接收。
//發送並訂閱
let entity = SocketD.newEntity().range(5,5).metaPut("videoId","1");
session.sendAndSubscribe("/demo/stream", entity).thenReply(reply=>{
//異步獲取答覆(會多次回調)
})
視頻演示效果:
- for H5
- for UniAPP