netty-socketio 概述

netty-socketio 概述

netty-socketio是一個開源的Socket.io服務器端的一個java的實現,它基於Netty框架,可用於服務端推送消息給客戶端。javascript

說到服務端推送技術,通常會涉及WebSocket,WebSocket是HTML5最新提出的規範,雖然主流瀏覽器都已經支持,但仍然可能有不兼容的狀況,爲了兼容全部瀏覽器,給程序員提供一致的編程體驗,SocketIO將WebSocket、AJAX和其它的通訊方式所有封裝成了統一的通訊接口,也就是說,使用SocketIO時不用擔憂兼容問題,底層會自動選用最佳的通訊方式。css

netty-socketio 框架事件流程

netty-socketio 示例demo

pom.xmlhtml

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.corundumstudio.socketio</groupId>
        <artifactId>netty-socketio</artifactId>
        <version>1.7.17</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.4</version>
        <scope>provided</scope>
    </dependency>

</dependencies>

啓動類 NettySocketioApplication前端

@SpringBootApplication
@Slf4j
public class NettySocketioApplication implements CommandLineRunner {

    public static void main(String[] args) {
        SpringApplication.run(NettySocketioApplication.class, args);
    }

    @Autowired
    private SocketIOServer socketIOServer;

    @Override
    public void run(String... strings) {
        socketIOServer.start();
        log.info("socket.io啓動成功!");
    }
}

Messagejava

@Data
public class Message {

    private String msg;
}

配置類 NettySocketioConfig程序員

@Configuration
public class NettySocketioConfig {
    /**
     * netty-socketio服務器
     */
    @Bean
    public SocketIOServer socketIOServer() {
        com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();
        config.setHostname("localhost");
        config.setPort(9092);

        SocketIOServer server = new SocketIOServer(config);
        return server;
    }

    /**
     * 用於掃描netty-socketio的註解,好比 @OnConnect、@OnEvent
     */
    @Bean
    public SpringAnnotationScanner springAnnotationScanner() {
        return new SpringAnnotationScanner(socketIOServer());
    }
}

消息處理器 MessageEventHandlerweb

@Component
@Slf4j
public class MessageEventHandler {

    @Autowired
    private SocketIOServer socketIoServer;

    public static ConcurrentMap<String, SocketIOClient> socketIOClientMap = new ConcurrentHashMap<>();

    /**
     * 客戶端鏈接的時候觸發
     *
     * @param client
     */
    @OnConnect
    public void onConnect(SocketIOClient client) {
        String mac = client.getHandshakeData().getSingleUrlParam("mac");
        //存儲SocketIOClient,用於發送消息
        socketIOClientMap.put(mac, client);
        //回發消息
        client.sendEvent("message", "onConnect back");
        log.info("客戶端:" + client.getSessionId() + "已鏈接,mac=" + mac);
    }

    /**
     * 客戶端關閉鏈接時觸發
     *
     * @param client
     */
    @OnDisconnect
    public void onDisconnect(SocketIOClient client) {
        log.info("客戶端:" + client.getSessionId() + "斷開鏈接");
    }

    /**
     * 客戶端事件
     *
     * @param client   客戶端信息
     * @param request 請求信息
     * @param data     客戶端發送數據
     */
    @OnEvent(value = "messageevent")
    public void onEvent(SocketIOClient client, AckRequest request, Message data) {
        log.info("發來消息:" + data);
        //回發消息
        client.sendEvent("messageevent", "我是服務器都安發送的信息");
        //廣播消息
        sendBroadcast();
    }

    /**
     * 廣播消息
     */
    public void sendBroadcast() {
        for (SocketIOClient client : socketIOClientMap.values()) {
            if (client.isChannelOpen()) {
                client.sendEvent("Broadcast", "當前時間", System.currentTimeMillis());
            }
        }

    }
}

html 頁面spring

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, user-scalable=no">
    <title>websocket-java-socketio</title>
    <script src="https://cdn.bootcss.com/socket.io/2.2.0/socket.io.js"></script>
</head>
<body>
<h1>Socket.io Test</h1>
<div><p id="status">Waiting for input</p></div>
<div><p id="message">hello world!</p></div>
<button id="connect" onClick='connect()'/>Connect</button>
<button id="disconnect" onClick='disconnect()'>Disconnect</button>
<button id="send" onClick='send()'/>Send Message</button>
</body>

<script type="text/javascript">

    /**
     * 前端js的 socket.emit("事件名","參數數據")方法,是觸發後端自定義消息事件的時候使用的,
     * 前端js的 socket.on("事件名",匿名函數(服務器向客戶端發送的數據))爲監聽服務器端的事件
     **/
    var socket = io.connect("http://localhost:9092?mac=2");
    var firstconnect = true;

    function connect() {
        if(firstconnect) {

            //socket.on('reconnect', function(){ status_update("Reconnected to Server"); });
            //socket.on('reconnecting', function( nextRetry ){ status_update("Reconnecting in "
            //+ nextRetry + " seconds"); });
            //socket.on('reconnect_failed', function(){ message("Reconnect Failed"); });
            //firstconnect = false;
        } else {
            socket.socket.reconnect();
        }
    }

    //監聽服務器鏈接事件
    socket.on('connect', function(){ status_update("Connected to Server"); });
    //監聽服務器關閉服務事件
    socket.on('disconnect', function(){ status_update("Disconnected from Server"); });
    //監聽服務器端發送消息事件
    socket.on('messageevent', function(data) {
        message(data)
        //console.log("服務器發送的消息是:"+data);
    });

    //斷開鏈接
    function disconnect() {
        socket.disconnect();
    }

    function message(data) {
        document.getElementById('message').innerHTML = "Server says: " + data;
    }

    function status_update(txt){
        document.getElementById('status').innerHTML = txt;
    }

    function esc(msg){
        return msg.replace(/</g, '<').replace(/>/g, '>');
    }
    //點擊發送消息觸發
    function send() {
        console.log("點擊了發送消息,開始向服務器發送消息")
        var msg = "我很好的,是的.";
        socket.emit('messageevent', {msgContent: msg});
    };
</script>
</html>

執行輸出

運行 SpringBoot 服務器編程

>  mvn spring-boot:run

點擊網頁按鈕後端

相關文章
相關標籤/搜索