Solon rpc 之 SocketD 協議 - 訊息鑑權模式

劉之西東發表於2021-01-12

Solon rpc 之 SocketD 協議系列
Solon rpc 之 SocketD 協議 - 概述
Solon rpc 之 SocketD 協議 - 訊息上報模式
Solon rpc 之 SocketD 協議 - 訊息應答模式
Solon rpc 之 SocketD 協議 - 訊息訂閱模式
Solon rpc 之 SocketD 協議 - RPC呼叫模式
Solon rpc 之 SocketD 協議 - 單連結雙向RPC模式
Solon rpc 之 SocketD 協議 - 訊息加密模式
Solon rpc 之 SocketD 協議 - 訊息鑑權模式

SocketD 是一種二進位制的點對點通訊協議,是一種新的網路通訊第七層協議。旨在用於分散式應用程式中。從這個意義上講,SocketD可以是RSocket等其他類似協議的替代方案。它的訊息協議規範具有非同步,背壓的雙向,多路複用,斷線重連,基於訊息等特性。暫時只提供Java實現,目前做為Solon rpc的sockte通道協議。

本案在訊息上報模式的基礎上增加簽權為例演示:

服務端

//啟動服務端
public class ServerApp {
    public static void main(String[] args) {
        //啟動Solon容器(SocketD bean&plugin 由solon容器管理)
        Solon.start(ServerApp.class, args, app -> app.enableSocketD(true));
    }
}

//定義服務端監聽
@ServerEndpoint
public class ServerListener implements Listener {
    @Override
    public void onOpen(Session session) {
        System.out.println("有客戶端鏈上來嘍...");
    }

    @Override
    public void onMessage(Session session, Message message) throws IOException {
        if (session.getHandshaked() == false) {
            //訊息是執行緒池分發的,確保鑑權時的訊息順序鎖一下
            synchronized (session) {
                onMessage0(session, message);
            }
        } else {
            onMessage0(session, message);
        }
    }

    private void onMessage0(Session session, Message message) throws IOException {
        //如果是握手,則做鑑權處理
        if (message.flag() == MessageFlag.handshake) {
            if (Utils.isEmpty(message.header())) {
                session.close();
            } else {
                Map<String, String> headers = HeaderUtil.decodeHeaderMap(message.header());
                if ("1".equals(headers.get("token"))) {
                    //如果token是1,則設為成功握手
                    System.out.println("籤權成功");
                    session.setHandshaked(true);
                } else {
                    session.close();
                }
            }

            return;
        }

        //沒有握手成功之前,不能做別的事;且自動斷開連結
        if (session.getHandshaked() == false) {
            System.out.println("這個客戶端很壞,沒簽權就想發包:(");
            session.close();
        }

        //如果是心跳,則乎略
        if (message.flag() == MessageFlag.heartbeat) {
            System.out.println("服務端:我收到心跳");
            return;
        }

        //業務處理
        System.out.println("服務端:我收到:" + message.bodyAsString());
    }
}

客戶端

//啟動客戶端
public class ClientApp {
    public static void main(String[] args) throws Throwable {
        //啟動Solon容器(SocketD bean&plugin 由solon容器管理)
        Solon.start(ClientApp.class, args);

        //建立會話(如果後端是WebSocekt,協議頭為:ws)
        Session session = SocketD.createSession("tcp://localhost:28080");

        //傳送業務握手(進行籤權)
        session.sendHandshake(Message.wrapHandshake("sn=1&token=1"));

        //設定30秒自動上發心跳(如果斷開了,也嘗試自動重鏈)
        session.sendHeartbeatAuto(30);

        //上報訊息
        session.send("Helloworld server!");
    }
}

附:示例原始碼

相關文章