1. 程式人生 > >JS使用WebSocket實現與Java圖形介面(swing)進行通訊

JS使用WebSocket實現與Java圖形介面(swing)進行通訊

背景:做專案的時候有過這樣的一個需求,在訪問某個網頁的時候進行登入,需要瀏覽器獲取電腦的硬體資源,但是通過瀏覽器直接讀取的方式有些不便,所以想到使用Java開發一個圖形應用介面的程式讀取電腦程式通過socket通訊傳輸給html頁面用於驗證。

寫在前面:在Java伺服器這端開發中,使用到一個jar包,Java-WebSocket-1.3.0.jar,首先引入這個包,這個核心包就是用來複制Java進行WebSocket伺服器的。

步驟1. 然後開始服務端編碼,建立核心服務類WsServer

import java.net.InetSocketAddress;

import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;

public class WsServer extends WebSocketServer {


    public WsServer(int port) {
        super(new InetSocketAddress(port));
    }

    public WsServer(InetSocketAddress address) {
        super(address);
    }

    @Override
    public void onOpen(WebSocket conn, ClientHandshake handshake) {
        // ws連線的時候觸發的程式碼,onOpen中我們不做任何操作

    }

    @Override
    public void onClose(WebSocket conn, int code, String reason, boolean remote) {
        //斷開連線時候觸發程式碼
        userLeave(conn);
        System.out.println(reason);
    }

    @Override
    public void onMessage(WebSocket conn, String message) {
        String msg = "收到資訊:"+message;
        System.out.println(msg);
        userJoin(conn,message);//使用者加入
        WsUtil.sendMessageToUser(conn,msg);
    }


    @Override
    public void onError(WebSocket conn, Exception ex) {
        //錯誤時候觸發的程式碼
        System.out.println("on error");
        ex.printStackTrace();
    }
    /**
     * 去除掉失效的websocket連結
     * @param conn
     */
    private void userLeave(WebSocket conn){
        WsUtil.removeUser(conn);
    }

    /**
     * 將websocket加入使用者池
     * @param conn
     * @param userName
     */
    private void userJoin(WebSocket conn,String userName){
        WsUtil.addUser(userName, conn);
    }

}

步驟2. 裡面用到了工具類WsUtil,程式碼如下:

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.java_websocket.WebSocket;

public class WsUtil {

    private static final Map<WebSocket, String> wsUserMap = new HashMap<WebSocket, String>();
    /**
     * 通過websocket連接獲取其對應的使用者
     *
     * @param conn
     * @return
     */
    public static String getUserByWs(WebSocket conn) {
        return wsUserMap.get(conn);
    }

    /**
     * 根據userName獲取WebSocket,這是一個list,此處取第一個
     * 因為有可能多個websocket對應一個userName(但一般是隻有一個,因為在close方法中,我們將失效的websocket連線去除了)
     *
     * @param user
     */
    public static WebSocket getWsByUser(String userName) {
        Set<WebSocket> keySet = wsUserMap.keySet();
        synchronized (keySet) {
            for (WebSocket conn : keySet) {
                String cuser = wsUserMap.get(conn);
                if (cuser.equals(userName)) {
                    return conn;
                }
            }
        }
        return null;
    }

    /**
     * 向連線池中新增連線
     *
     * @param inbound
     */
    public static void addUser(String userName, WebSocket conn) {
        wsUserMap.put(conn, userName); // 新增連線
    }

    /**
     * 獲取所有連線池中的使用者,因為set是不允許重複的,所以可以得到無重複的user陣列
     *
     * @return
     */
    public static Collection<String> getOnlineUser() {
        List<String> setUsers = new ArrayList<String>();
        Collection<String> setUser = wsUserMap.values();
        for (String u : setUser) {
            setUsers.add(u);
        }
        return setUsers;
    }

    /**
     * 移除連線池中的連線
     *
     * @param inbound
     */
    public static boolean removeUser(WebSocket conn) {
        if (wsUserMap.containsKey(conn)) {
            wsUserMap.remove(conn); // 移除連線
            return true;
        } else {
            return false;
        }
    }

    /**
     * 向特定的使用者傳送資料
     *
     * @param user
     * @param message
     */
    public static void sendMessageToUser(WebSocket conn, String message) {
        if (null != conn && null != wsUserMap.get(conn)) {
            conn.send(message);
        }
    }

    /**
     * 向所有的使用者傳送訊息
     *
     * @param message
     */
    public static void sendMessageToAll(String message) {
        Set<WebSocket> keySet = wsUserMap.keySet();
        synchronized (keySet) {
            for (WebSocket conn : keySet) {
                String user = wsUserMap.get(conn);
                if (user != null) {
                    conn.send(message);
                }
            }
        }
    }

}

步驟3. 最後在Main類中開啟主服務:

import org.java_websocket.WebSocketImpl;

public class Main {
    public static void main(String[] args) {
        WebSocketImpl.DEBUG = false;
        int port = 9090; // 埠
        WsServer s = new WsServer(port);//例項化一個監聽伺服器
        s.start();//啟動伺服器
    }
}

步驟4. 點選執行按鈕就可以在9090埠開啟該服務,接下來進行HTML的編碼

<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <title>WebSocket</title>
 </head>
 <body>
  <script>

	var socket;

	function connectServer(){

		var socket_ip="127.0.0.1";
		
		socket= new WebSocket('ws://'+socket_ip+':9090');

		socket.onopen = function(event)
		{
			console.log("連線服務成功!");
			sendMsg()
			
		};


		// 監聽訊息
		socket.onmessage = function(event)
		{
			console.log('Client received a message',event);
			console.log(event.data);
		};

		// 監聽Socket的關閉
		socket.onclose = function(event)
		{
		
		};

		socket.onerror = function(event) {
			//alert('無法連線到:' + socket_ip);
		};
	}

	connectServer()

	function sendMsg(){
		socket.send("你好!"); 
	}
  </script>
 </body>
</html>

結果展示:html連線上Java服務程式後併發送“你好”字樣,Java收到後並給與了回覆