1. 程式人生 > >socket.io資料推送

socket.io資料推送

socketio簡介
Socket.io是一個WebSocket庫,包括了客戶端的js和伺服器端的nodejs,它的目標是構建可以在不同瀏覽器和移動裝置上使用的實時應用。它會自動根據瀏覽器從WebSocket、AJAX長輪詢、Iframe流等等各種方式中選擇最佳的方式來實現網路實時應用,非常方便和人性化,而且支援的瀏覽器最低達IE5.5.

socket.io特點
實時分析:將資料推送到客戶端,這些客戶端會被表示為實時計數器,圖表或日誌客戶。
實時通訊和聊天:只需幾行程式碼便可寫成一個Socket.IO的”Hello,World”聊天應用。
二進位制流傳輸:從1.0版本開始,Socket.IO支援任何形式的二進位制檔案傳輸,例如:圖片,視訊,音訊等。
文件合併:允許多個使用者同時編輯一個文件,並且能夠看到每個使用者做出的修改。

Demo簡介

服務端使用netty-socketio,客戶端使用socket.io.js。
本例完全來自上面的連結,這裡只是測試效果以及做備忘。本例實現的功能是一個使用者向另外一個用法發小訊息。

maven中新增依賴

<dependency>
  <groupId>com.corundumstudio.socketio</groupId>
  <artifactId>netty-socketio</artifactId>
  <version>1.7.3</version>
</dependency
>

服務端SocketServer

@Component
public class ChatServer implements InitializingBean {
    @Autowired
    private EventListenner eventListenner;
    @Override
    public void afterPropertiesSet() throws Exception {
        Configuration config = new Configuration();
        config.setPort(9098);
        SocketConfig socketConfig = new
SocketConfig(); socketConfig.setReuseAddress(true); socketConfig.setTcpNoDelay(true); socketConfig.setSoLinger(0); config.setSocketConfig(socketConfig); config.setHostname("localhost"); SocketIOServer server = new SocketIOServer(config); server.addListeners(eventListenner); server.start(); System.out.println("啟動正常"); } }

快取類,快取客戶端連線

@Component("clientCache")
public class SocketIOClientCache {
    //String:EventType型別
    private Map<String,SocketIOClient> clients=new ConcurrentHashMap<String,SocketIOClient>();
    //使用者傳送訊息新增
    public void addClient(SocketIOClient client,MsgBean msgBean){
        clients.put(msgBean.getFrom(),client);
    }
    //使用者退出時移除
    public void remove(MsgBean msgBean) {
        clients.remove(msgBean.getFrom());
    }
    //獲取所有
    public  SocketIOClient getClient(String to) {
        return clients.get(to);
    }
}

訊息傳送的類

@Service("socketIOResponse")
public class SocketIOResponse {
    public void sendEvent(SocketIOClient client, MsgBean bean) {
        System.out.println("推送訊息");
        client.sendEvent("OnMSG", bean);
    }
}

事件監聽器

@Service("eventListenner")
public class EventListenner {
    @Resource(name = "clientCache")
    private SocketIOClientCache clientCache;
    @Resource(name = "socketIOResponse")
    private SocketIOResponse socketIOResponse;
    @OnConnect
    public void onConnect(SocketIOClient client) {
       System.out.println("建立連線");
    }
    @OnEvent("OnMSG")
    public void onSync(SocketIOClient client, MsgBean bean) {
        System.out.printf("收到訊息-from: %s to:%s\n", bean.getFrom(), bean.getTo());
        clientCache.addClient(client, bean);
        SocketIOClient ioClients = clientCache.getClient(bean.getTo());
        System.out.println("clientCache");
        if (ioClients == null) {
            System.out.println("你傳送訊息的使用者不線上");
            return;
        }
        socketIOResponse.sendEvent(ioClients,bean);
    }
    @OnDisconnect
    public void onDisconnect(SocketIOClient client) {
        System.out.println("關閉連線");
    }
}

訊息bean

public class MsgBean { 
    private String from;
    private String to;
    private String content;
    public String getFrom() {
        return from;
    }
    public void setFrom(String from) {
        this.from = from;
    }
    public String getTo() {
        return to;
    }
    public void setTo(String to) {
        this.to = to;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    @Override
    public String toString() {
        return "MsgBean [from=" + from + ", to=" + to + ", content=" + content + "]";
    }
}

頁面

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
    <title>socket.io demo</title>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
    <script type="text/javascript" th:src="@{/js/jquery.js}"></script>
    <script type="text/javascript" th:src="@{/js/socket.io.min.js}"></script>
    <style>
        body {
            padding: 20px;
        }
        #console {
            height: 400px;
            overflow: auto;
        }
        .username-msg {
            color: orange;
        }
        .connect-msg {
            color: green;
        }
        .disconnect-msg {
            color: red;
        }
        .send-msg {
            color: #888
        }
    </style>
</head>
<body>
<h1>Netty-socketio chat demo</h1>
<br />
<div id="console" class="well"></div>
<form class="well form-inline" onsubmit="return false;">
    <input id="from" class="input-xlarge" type="text" placeholder="from. . . " />
    <input id="to" class="input-xlarge" type="text" placeholder="to. . . " />
    <input id="content" class="input-xlarge" type="text" placeholder="content. . . " />
    <button type="button" onClick="sendMessage()" class="btn">Send</button>
    <button type="button" onClick="sendDisconnect()" class="btn">Disconnect</button>
</form>
</body>
<script type="text/javascript">
    var socket = io.connect('http://localhost:9098');
    socket.on('connect',function() {
        output('<span class="connect-msg">Client has connected to the server!</span>');
    });
    socket.on('OnMSG', function(data) {
        output('<span class="username-msg">' + data.content + ' : </span>');
    });
    socket.on('disconnect',function() {
        output('<span class="disconnect-msg">The client has disconnected! </span>');
    });
    function sendDisconnect() {
        socket.disconnect();
    }
    function sendMessage() {
        var from = $("#from").val();
        var to = $("#to").val();
        var content = $('#content').val();
        socket.emit('OnMSG', {
            from : from,
            to : to,
            content : content
        });
    }
    function output(message) {
        console.log(message)
        var currentTime = "<span>" + new Date() + "</span>";
        var element = $("<div>" + currentTime + " " + message + "</div><br/>");
        $('#console').prepend(element);
    }
</script>
</html>

說明:工程基於springboot,關於springboot相關的內容並未給出。

測試

瀏覽器2個標籤頁分頁輸入地址,進入到聊天頁面。
標籤頁1

我們假定標籤頁1使用者為admin,標籤頁2使用者為test。
標籤頁1:admin向test傳送1條訊息,點擊發送,切換到標籤頁2,發現並沒有訊息。因為這個時候快取中沒有test,所以沒有傳送成功。
標籤頁2:test向admin傳送1條訊息。

切換到標籤頁1,可以發現已經接受到test傳送的訊息

我們F12開啟開發人員工具,可以看到多次傳送訊息並沒有產生新的請求。

問題

1.中文亂碼
尚未找到解決方案。