springboot Websocket 通信測試

  • springboot項目結(jié)構(gòu),也可用spring項目,和框架沒有關(guān)系胖眷,沒有影響

H5和H5之間通信
H5和Andorid之間通信
Andorid和Andorid之間通信
H5通過http協(xié)議調(diào)用接口發(fā)送消息-給移動Andorid碳却、H5等
后臺支持語言:java
前端支持語言:Andorid(java)、H5(html)妈拌、jsp等
發(fā)送:發(fā)送給所有連接者、發(fā)送給所有在線者、發(fā)送給指定用戶桦山、及(發(fā)送對象)用戶不在線處理
注:把連接地址改了,可以直接使用復(fù)制代碼測試使用醋旦;

H5和Andorid測試頁面:

Andorid測試頁面 --消息發(fā)送者 發(fā)送指定用戶 【消息接收者1】恒水,也可以發(fā)送所有人
Andorid測試頁面.jpg
消息接收者1 消息接收者2
測試頁面1.jpg
測試頁面2.jpg
通過Http發(fā)送測試頁面
發(fā)送消息給所有在線用戶 發(fā)送消息給指定在線用戶 --【測試用戶 -張三】
http測試發(fā)送消息給所有在線用戶.jpg
http測試發(fā)送消息給指定在線用戶.jpg
測試用戶李四 測試用戶張三
測試用戶【李四】.jpg
測試用戶【張三】.jpg

java后臺代碼

引入依賴:
<!--集成移動和H5的java_websocket-->
        <dependency>
            <groupId>org.java-websocket</groupId>
            <artifactId>Java-WebSocket</artifactId>
            <version>1.3.0</version>
        </dependency>

springboot項目結(jié)構(gòu),也可用spring項目饲齐,和框架沒有關(guān)系钉凌,沒有影響

代碼類路徑.png

1.WebSocketPool自定義工具類

主要是連接池,存用戶和WebSocket連接

自定義 WebSocketPool.java

package com.dist.utils;

import org.java_websocket.WebSocket;

import java.util.*;

public class WebSocketPool {
    //連接-用戶名
    private static final Map<WebSocket, String> userconnections = new HashMap<WebSocket, String>();
      
    /** 
     * 獲取用戶名 
     * @param conn 
     * @return 
     */  
    public static String getUserByKey(WebSocket conn) {  
        return userconnections.get(conn);  
    }  
  
    /** 
     * 獲取在線總數(shù) 
     * @return 
     */  
    public static int getUserCount() {  
        return userconnections.size();  
    }  
  
    /** 
     * 獲取WebSocket 
     * @param user 
     * @return 
     */  
    public static WebSocket getWebSocketByUser(String user) {  
        Set<WebSocket> keySet = userconnections.keySet();
        synchronized (keySet) {  
            for (WebSocket conn : keySet) {  
                String cuser = userconnections.get(conn);  
                if (cuser.equals(user)) {  
                    return conn;  
                }  
            }  
        }  
        return null;  
    }  
  
    /** 
     * 向連接池中添加連接 
     * @param user 
     * @param conn 
     */  
    public static void addUser(String user, WebSocket conn) {  
        userconnections.put(conn, user); // 添加連接  
    }

    /**
     * 獲取所有連接池
     */
    public static Set<WebSocket> getAllWebSocket() {
            return userconnections.keySet();
    }

    /**
     * 移除連接池中的連接
     * @param conn
     * @return
     */
    public static boolean removeUser(WebSocket conn) {
        if (userconnections.containsKey(conn)) {
            userconnections.remove(conn); // 移除連接
            return true;
        } else
            return false;
    }
  
    /** 
     * 獲取所有的在線用戶 
     * @return 
     */  
    public static Collection<String> getOnlineUser() {
        List<String> setUsers = new ArrayList<String>();
        Collection<String> setUser = userconnections.values();  
        for (String u: setUser) {  
            setUsers.add(u);  
        }  
        return setUsers;  
    }
  
    /** 
     * 向特定的用戶發(fā)送數(shù)據(jù) 
     * @param conn 
     * @param message 
     */  
    public static void sendMessageToOnlineUser(WebSocket conn, String message) {
        if (null != conn) {  
            conn.send(message);  
        }  
    }

    /**
     * 向所有在線用戶發(fā)送消息
     * @param message
     */
    public static void sendMessageToOnlineAllUser(String message) {
        Set<WebSocket> keySet = userconnections.keySet();  
        synchronized (keySet) {
            for (WebSocket conn : keySet) {  
                String user = userconnections.get(conn);  
                if (user != null) { conn.send(message);  
                }  
            }  
        }  
    }  
}

2.創(chuàng)建房間類

為的是開啟房間

ChatServer.java

package com.dist.service;

import com.dist.utils.WebSocketPool;
import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.Set;

/**
 * 與不同的客戶端進(jìn)行通訊的思路為:
 * Step1:在連接成功的時候捂人,向服務(wù)器發(fā)送自己的用戶名御雕,服務(wù)器做用戶標(biāo)記;
 * Step2: 發(fā)送消息滥搭,格式為“XX@XXX”酸纲,@前面表示將要發(fā)送的對象,“all”表示群發(fā)瑟匆,@后面表示發(fā)送的消息闽坡。
 */
public class ChatServer extends WebSocketServer {

    private String username;

    public ChatServer(int port) throws UnknownHostException {
        super(new InetSocketAddress(port));
    }

    public ChatServer(InetSocketAddress address) {
        super(address);
        System.out.println("地址:"+address);
    }

    @Override
    public void onOpen(WebSocket conn, ClientHandshake handshake) {

        System.out.println("連接:"+conn);

        sendToAll(conn.getRemoteSocketAddress().getAddress().getHostAddress()
                + " 進(jìn)入房間 !");

        System.out.println(conn.getRemoteSocketAddress().getAddress()
                .getHostAddress()
                + " 進(jìn)入房間 脓诡!");
    }

    @Override
    public void onClose(WebSocket conn, int code, String reason, boolean remote) {

        sendToAll(conn.getRemoteSocketAddress().getAddress().getHostAddress()
                + " 離開房間 无午!");

        System.out.println(conn.getRemoteSocketAddress().getAddress()
                .getHostAddress()
                + " 離開房間 !");

        //觸發(fā)關(guān)閉事件
        userLeave(conn);
    }

    //消息發(fā)送
    @Override
    public void onMessage(WebSocket conn, String message) {

        //判斷是否是第一次接收的消息
        boolean isfirst = true;

        /*sendToAll("["
                + conn.getRemoteSocketAddress().getAddress().getHostAddress()
                + "]" + message);*/

        System.out.println("["
                + conn.getRemoteSocketAddress().getAddress().getHostAddress()
                + "]" + message);

        //判斷是否已在連接池中
        Set<WebSocket> webSockets=WebSocketPool.getAllWebSocket();
        for (WebSocket webSocket : webSockets){
            if (webSocket.equals(conn)){
                isfirst =false;
            }
        }

        if (isfirst) {
            this.username = message;
            //客戶端發(fā)送消息到服務(wù)器是觸發(fā)事件
            if (message != null){
                //判斷用戶是否已經(jīng)在線
                WebSocket webSocketByUser = WebSocketPool.getWebSocketByUser(message);
                if (null == webSocketByUser){
                    //將用戶加入連接池-在線
                    this.userJoin(username, conn);
                    System.out.println("用戶" + username + "上線,在線人數(shù):" + WebSocketPool.getUserCount());
                }else {
                    WebSocketPool.sendMessageToOnlineUser(conn,"["+username+"] 用戶已在線,請您換個用戶登錄祝谚!");
                }
            }
        } else {
            String[] msg = message.split("@", 2);//以@為分隔符把字符串分為xxx和xxxxx兩部分,msg[0]表示發(fā)送至的用戶名宪迟,all則表示發(fā)給所有人
            if (msg[0].equals("all")) {
                sendToAll(msg[1]);
            } else {
                //指定用戶發(fā)送消息
                sendMessageToUser(conn,msg[0], msg[1]);
            }
        }
    }

    //異常拋出
    @Override
    public void onError(WebSocket conn, Exception e) {
        e.printStackTrace();
        if (conn != null) {
            conn.close();
        }
    }

    // 發(fā)送給所有進(jìn)入房間的人
    private void sendToAll(String text) {
        Collection<WebSocket> conns = connections();
        synchronized (conns) {
            for (WebSocket client : conns) {
                client.send(text);
            }
        }
    }

    // 測試
    public static void main(String[] args) throws InterruptedException,
            IOException {
        /*int port = 8887;

        ChatServer server = new ChatServer(port);
        server.start();

        System.out.println("房間已開啟,等待客戶端接入交惯,端口號: " + server.getPort());

        BufferedReader webSocketIn = new BufferedReader(new InputStreamReader(
                System.in));

        while (true) {
            String stringIn = webSocketIn.readLine();
            // 發(fā)送給所有的聊天者
            server.sendToAll(stringIn);
        }*/
    }

    /**
     * 用戶下線處理
     * @param conn
     */
    public void userLeave(org.java_websocket.WebSocket conn) {
        String user = WebSocketPool.getUserByKey(conn);
        boolean b = WebSocketPool.removeUser(conn); // 在連接池中移除連接
        if (b) {
            WebSocketPool.sendMessageToOnlineAllUser(user); // 把當(dāng)前用戶從所有在線用戶列表中刪除
            String leaveMsg = "[系統(tǒng)]" + user + "下線了";
            WebSocketPool.sendMessageToOnlineAllUser(leaveMsg); // 向在線用戶發(fā)送當(dāng)前用戶退出的信息
        }
    }

    /**
     * 用戶上線處理
     * @param user
     * @param conn
     */
    public void userJoin(String user, org.java_websocket.WebSocket conn) {
        WebSocketPool.sendMessageToOnlineAllUser(user); // 把當(dāng)前用戶加入到所有在線用戶列表中
        String joinMsg = "[系統(tǒng)]" + user + "上線了次泽!";
        WebSocketPool.sendMessageToOnlineAllUser(joinMsg); // 向所有在線用戶推送當(dāng)前用戶上線的消息
        WebSocketPool.addUser(user, conn); // 向連接池添加當(dāng)前的連接的對象
        WebSocketPool.sendMessageToOnlineUser(conn, WebSocketPool.getOnlineUser().toString());  // 向當(dāng)前連接發(fā)送當(dāng)前在線用戶的列表

    }

    /**
     * 發(fā)送消息給指定用戶
     * @param currentConnection 當(dāng)前連接
     * @param user  發(fā)送對象
     * @param message 消息
     */
    public void sendMessageToUser(WebSocket currentConnection,String user,String message){
        WebSocket conn = WebSocketPool.getWebSocketByUser(user);  //獲取發(fā)送對象用戶的在線連接
        if (null != conn){
            //向特定在線用戶發(fā)送消息
            WebSocketPool.sendMessageToOnlineUser(conn,message);
            //同時發(fā)送消息給當(dāng)前用戶
            WebSocketPool.sendMessageToOnlineUser(currentConnection,message);
        }else {
            WebSocketPool.sendMessageToOnlineUser(currentConnection,"["+user+"] 用戶不在線,請您稍后發(fā)送!");
            System.out.println("["+user+"] 用戶不在線,請您稍后發(fā)送席爽!");
            WebSocketPool.sendMessageToOnlineUser(currentConnection,"當(dāng)前在線人數(shù):"+WebSocketPool.getUserCount()+"  有:"+WebSocketPool.getOnlineUser());
        }
    }
}

3.Http發(fā)送消息

在controller層 創(chuàng)建WebSocketController.java

package com.dist.controller;

import com.dist.utils.WebSocketPool;
import org.java_websocket.WebSocket;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author zhengja@dist.com.cn
 * @data 2019/4/17 14:54
 */
@RestController
@RequestMapping("/WebSocket")
public class WebSocketController {

     //推送給所有在線用戶
    @RequestMapping(value = "v1/sendAllUser", method = RequestMethod.GET)
    public void sendAllUser(@RequestParam String message){
        //推送給所有在線用戶
        WebSocketPool.sendMessageToOnlineAllUser(message);
    }
  
    //推送給在線的指定用戶
    @RequestMapping(value = "v1/sendUser", method = RequestMethod.GET)
    public void loginWithDevice(@RequestParam String pushObject,
                                @RequestParam String message){
        //推送的設(shè)備對象
        List<String> userlist = null;
        if (pushObject == null || "".equals(pushObject)) {
            System.out.println("推送對象不能為nuul");
        } else {
            userlist = new ArrayList<>(Arrays.asList(pushObject.split(",")));
        }
        for (String user : userlist){
            //根據(jù)用戶查找推送的連接對象是否在線
            WebSocket webSocketByUser = WebSocketPool.getWebSocketByUser(user);
            if (null != webSocketByUser){
                //推送給在線的指定用戶
                WebSocketPool.sendMessageToOnlineUser(webSocketByUser,message);
            }else {
                //未推送成功處理模塊
                System.out.println("用戶 【"+user+"】 不在線意荤,推送失敗 ! ");
            }
        }
    }

}

4.創(chuàng)建啟動任務(wù)

項目起動后自動啟動這個任務(wù)-開啟房間

TestStarts.java

import com.dist.service.ChatServer;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

@Component
public class TestStarts implements InitializingBean {

    @Override
    public void afterPropertiesSet() throws Exception {
        int port = 8887;

        ChatServer server = new ChatServer(port);
        server.start();
        System.out.println("項目啟動中:房間已開啟");
        System.out.println("等待客戶端接入的端口號: " + server.getPort());

    }
}

H5前端代碼:

H5測試頁面:引入jquery.js (放同級目錄)


頁面目錄.png

目前測試頁面上的數(shù)據(jù)信息是寫死的只锻,自己可以重后臺獲取數(shù)據(jù)玖像,寫成動態(tài)的

測試頁面1

H5-WebSocket.html

注意:var wsUri ="ws://129.204.207.127:8887"; 把地址改成自己的服務(wù)器地址,端口不是服務(wù)器的齐饮,是TestStarts.java啟動任務(wù)自定義創(chuàng)建的

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
<head>
    <meta charset="UTF-8">
    <title>H5-WebSocket Test</title>
    <script src="jquery.js"></script>
</head>
<body>

<br name="#" method="post">
    <!--YOUR DATA AREA-->
    <label id="a">當(dāng)前用戶</label>
    <select id="loginsel">
        <option value="2">李四</option>
        <option value="3">張三</option>
        <option value="4">王二</option>
    </select>
    <input type="button" value="連接" id="btnconnection" onclick="connectionAction()"/>
    <input type="button" value="斷開" id="btndisconnect" onclick="disconnectAction()"/></br></br>
    <label id="b">發(fā)送對象</label>
    <select id="sel">
        <option value="1" selected>all</option>
        <option value="2">李四</option>
        <option value="3">張三</option>
        <option value="4">王二</option>
    </select>
    <label id="msg">要發(fā)送的信息</label><input type="text" id="message">
    <input type="button" id="btnsendMessage" value="發(fā)送消息" onclick="sendMessageAction()">
</form>

<script language="javascript"type="text/javascript">
    var wsUri ="ws://129.204.207.127:8887";
    var output;
    var message;
    var userToMessage;
    var websocket;

    function connectionAction() {
        output = document.getElementById("output");
        //websocket的房間
        websocket = new WebSocket(wsUri);
        //打開連接
        websocket.onopen = function(evt) {
            var loginuser = $('#loginsel option:selected').text();
            websocket.send(loginuser);
        };
        websocket.onmessage = function(evt) {
            onMessage(evt)
        };
        websocket.onerror = function(evt) {
            onError(evt)
        };
        $("#loginsel").attr("disabled","disabled");
        $("#btnconnection").attr("disabled","disabled");

        $("#btndisconnect").removeAttr("disabled");
        $("#sel").removeAttr("disabled");
        $("#msg").removeAttr("disabled");
        $("#btnsendMessage").removeAttr("disabled");
    }

    //給指定用戶發(fā)送消息
    function sendMessageAction() {
        var sendTouser = $('#sel option:selected').text();
        message =document.getElementById("message").value;
        userToMessage = sendTouser +"@"+message;
        websocket.send(userToMessage);
    }

    //斷開連接
    function disconnectAction() {
        websocket.close();
        writeToScreen("您已斷開連接");

        $("#loginsel").removeAttr("disabled");
        $("#btnconnection").removeAttr("disabled");

        $("#btndisconnect").attr("disabled","disabled");
        $("#sel").attr("disabled","disabled");
        $("#msg").attr("disabled","disabled");
        $("#btnsendMessage").attr("disabled","disabled");
    }

  /*  function init() {
        output = document.getElementById("output");
        testWebSocket();
    }
    function testWebSocket() {
        websocket = new WebSocket(wsUri);
        websocket.onopen = function(evt) {
            onOpen(evt)
        };
        websocket.onmessage = function(evt) {
            onMessage(evt)
        };
        websocket.onerror = function(evt) {
            onError(evt)
        };
        websocket.onclose = function(evt) {
            onClose(evt)
        };
    }*/

    function onOpen(evt) {
        writeToScreen("CONNECTED");
        doSend("Zhansna");
    }

    function onClose(evt) {
        writeToScreen("您已斷開連接");
        websocket.close();
    }

    //接收消息
    function onMessage(evt) {
        writeToScreen('<span style="color: blue;">RESPONSE: '+ evt.data+'</span>');
    }

    function onError(evt) {
        writeToScreen('<span style="color: red;">ERROR:</span> '+ evt.data);
    }

    function doSend(message) {
        writeToScreen("SENT: " + message);
        websocket.send(message);
    }

    function writeToScreen(message) {
        var pre = document.createElement("p");
        pre.style.wordWrap = "break-word";
        pre.innerHTML = message;
        output.appendChild(pre);
    }

    window.addEventListener("load", init, false);
</script>
<h2>WebSocket Test</h2>
<div id="output"></div>
</body>
</html>
測試頁面2

H5-WebSocket2.html

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
<head>
    <meta charset="UTF-8">
    <title>H5-WebSocket Test2</title>
    <script src="jquery.js"></script>
</head>
<body>

<br name="#" method="post">
    <!--YOUR DATA AREA-->
    <label id="a">當(dāng)前用戶</label>
    <select id="loginsel">
        <option value="2">李四</option>
        <option value="3">張三</option>
        <option value="4">王二</option>
    </select>
    <input type="button" value="連接" id="btnconnection" onclick="connectionAction()"/>
    <input type="button" value="斷開" id="btndisconnect" onclick="disconnectAction()"/></br></br>
    <label id="b">發(fā)送對象</label>
    <select id="sel">
        <option value="1" selected>all</option>
        <option value="2">李四</option>
        <option value="3">張三</option>
        <option value="4">王二</option>
    </select>
    <label id="msg">要發(fā)送的信息</label><input type="text" id="message">
    <input type="button" id="btnsendMessage" value="發(fā)送消息" onclick="sendMessageAction()">
</form>

<script language="javascript"type="text/javascript">
    var wsUri ="ws://129.204.207.127:8887";
    var output;
    var message;
    var userToMessage;
    var websocket;

    function connectionAction() {
        output = document.getElementById("output");
        //websocket的房間
        websocket = new WebSocket(wsUri);
        //打開連接
        websocket.onopen = function(evt) {
            var loginuser = $('#loginsel option:selected').text();
            websocket.send(loginuser);
        };
        websocket.onmessage = function(evt) {
            onMessage(evt)
        };
        websocket.onerror = function(evt) {
            onError(evt)
        };
        $("#loginsel").attr("disabled","disabled");
        $("#btnconnection").attr("disabled","disabled");

        $("#btndisconnect").removeAttr("disabled");
        $("#sel").removeAttr("disabled");
        $("#msg").removeAttr("disabled");
        $("#btnsendMessage").removeAttr("disabled");
    }

    //給指定用戶發(fā)送消息
    function sendMessageAction() {
        var sendTouser = $('#sel option:selected').text();
        message =document.getElementById("message").value;
        userToMessage = sendTouser +"@"+message;
        websocket.send(userToMessage);
    }

    //斷開連接
    function disconnectAction() {
        websocket.close();
        writeToScreen("您已斷開連接");

        $("#loginsel").removeAttr("disabled");
        $("#btnconnection").removeAttr("disabled");

        $("#btndisconnect").attr("disabled","disabled");
        $("#sel").attr("disabled","disabled");
        $("#msg").attr("disabled","disabled");
        $("#btnsendMessage").attr("disabled","disabled");
    }

  /*  function init() {
        output = document.getElementById("output");
        testWebSocket();
    }
    function testWebSocket() {
        websocket = new WebSocket(wsUri);
        websocket.onopen = function(evt) {
            onOpen(evt)
        };
        websocket.onmessage = function(evt) {
            onMessage(evt)
        };
        websocket.onerror = function(evt) {
            onError(evt)
        };
        websocket.onclose = function(evt) {
            onClose(evt)
        };
    }*/

    function onOpen(evt) {
        writeToScreen("CONNECTED");
        doSend("Zhansna");
    }

    function onClose(evt) {
        writeToScreen("您已斷開連接");
        websocket.close();
    }

    //接收消息
    function onMessage(evt) {
        writeToScreen('<span style="color: blue;">RESPONSE: '+ evt.data+'</span>');
    }

    function onError(evt) {
        writeToScreen('<span style="color: red;">ERROR:</span> '+ evt.data);
    }

    function doSend(message) {
        writeToScreen("SENT: " + message);
        websocket.send(message);
    }

    function writeToScreen(message) {
        var pre = document.createElement("p");
        pre.style.wordWrap = "break-word";
        pre.innerHTML = message;
        output.appendChild(pre);
    }

    window.addEventListener("load", init, false);
</script>
<h2>WebSocket Test2</h2>
<div id="output"></div>
</body>
</html>

現(xiàn)在就可以實現(xiàn)H5頁面之間的通信啦
以上只是H5測試用例捐寥,真正用的項目中也是這樣笤昨,只不過,要根據(jù)項目需求該代碼邏輯握恳。我的項目就是版本推送和反饋消息的及時推送瞒窒;

Andorid測試代碼:

測試最好創(chuàng)建空白的Andorid app

在.gradle 引入java-websocket依賴

dependencies{
  implementation 'org.java-websocket:Java-WebSocket:1.3.0'
}
頁面代碼

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    >

    <ScrollView
        android:id="@+id/svChat"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <Spinner
                android:id="@+id/spDraft"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />

            <!-- ws://192.168.1.104:80/JSR356-WebSocket/websocket/ -->
            <!-- ws://192.168.1.104:8887 -->
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal">

                <EditText
                    android:id="@+id/etAddress"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="4" />

                <Spinner
                    android:id="@+id/spAddress"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="2" />
            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal">
                <!--選擇登錄用戶-->
                <EditText
                    android:id="@+id/etloginName"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="4"
                    android:hint="選著登錄名" /><!--Jack-->
                <Spinner
                    android:id="@+id/sploginName"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="2" />
            </LinearLayout>

            <Button
                android:id="@+id/btnConnect"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="連接" />

            <Button
                android:id="@+id/btnClose"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="斷開" />

            <EditText
                android:id="@+id/etDetails"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@null"
                android:focusable="false"
                android:focusableInTouchMode="false"
                android:paddingTop="5dp"
                android:paddingBottom="5dp"
                android:textSize="13dp" />

            <Button
                android:id="@+id/btnClearDetails"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="清除聊天記錄" />
        </LinearLayout>
    </ScrollView>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Spinner
            android:id="@+id/spName"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="3"/>

        <!--<EditText
            android:id="@+id/etName"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:hint="發(fā)送對象"
            android:text=""
            android:layout_weight="1"/>--><!--Jack-->

        <EditText
            android:id="@+id/etMessage"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:hint="發(fā)送消息內(nèi)容"
            android:layout_weight="4"/>

        <Button
            android:id="@+id/btnSend"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="發(fā)送"/>
    </LinearLayout>
</LinearLayout>

邏輯代碼

MainActivity.java

package com.dist.myapplication;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ScrollView;
import android.widget.Spinner;

import org.java_websocket.WebSocketImpl;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft;
import org.java_websocket.drafts.Draft_10;
import org.java_websocket.drafts.Draft_17;
import org.java_websocket.drafts.Draft_75;
import org.java_websocket.drafts.Draft_76;
import org.java_websocket.handshake.ServerHandshake;

import java.net.URI;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private ScrollView svChat;
    private Spinner spDraft;
    private EditText etAddress;
    private Spinner spAddress;

    private Spinner sploginName;
    private EditText etloginName;

    private Button btnConnect;
    private Button btnClose;
    private EditText etDetails;
    private Button btnClearDetails;

    private Spinner spName;
    //private EditText etName;
    private EditText etMessage;
    private Button btnSend;

    private WebSocketClient client;// 連接客戶端
    private DraftInfo selectDraft;// 連接協(xié)議

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        svChat = (ScrollView) findViewById(R.id.svChat);
        spDraft = (Spinner) findViewById(R.id.spDraft);
        etAddress = (EditText) findViewById(R.id.etAddress);
        spAddress = (Spinner) findViewById(R.id.spAddress);

        sploginName = (Spinner) findViewById(R.id.sploginName);
        etloginName = (EditText) findViewById(R.id.etloginName);

        btnConnect = (Button) findViewById(R.id.btnConnect);
        btnClose = (Button) findViewById(R.id.btnClose);
        etDetails = (EditText) findViewById(R.id.etDetails);
        btnClearDetails = (Button) findViewById(R.id.btnClearDetails);

        spName = (Spinner) findViewById(R.id.spName);
        //etName = (EditText) findViewById(R.id.etName);
        etMessage = (EditText) findViewById(R.id.etMessage);
        btnSend = (Button) findViewById(R.id.btnSend);

        DraftInfo[] draftInfos = {new DraftInfo("WebSocket協(xié)議Draft_17", new Draft_17()), new DraftInfo
                ("WebSocket協(xié)議Draft_10", new Draft_10()), new DraftInfo("WebSocket協(xié)議Draft_76", new Draft_76()), new
                DraftInfo("WebSocket協(xié)議Draft_75", new Draft_75())};// 所有連接協(xié)議
        selectDraft = draftInfos[0];// 默認(rèn)選擇第一個連接協(xié)議

        ArrayAdapter<DraftInfo> draftAdapter = new ArrayAdapter<DraftInfo>(this, android.R.layout
                .simple_spinner_item, draftInfos);
        spDraft.setAdapter(draftAdapter);
        spDraft.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                selectDraft = (DraftInfo) spDraft.getItemAtPosition(position);// 選擇連接協(xié)議

                etDetails.append("當(dāng)前連接協(xié)議:" + selectDraft.draftName + "\n");

                Log.e("wlf", "選擇連接協(xié)議:" + selectDraft.draftName);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                selectDraft = null;// 清空

                Log.e("wlf", "未選擇任何連接協(xié)議");
            }
        });

        ServerInfo[] serverInfos = {new ServerInfo("連接內(nèi)網(wǎng)web后臺", "ws://192.168.2.114:8887"),new ServerInfo("連接外網(wǎng)web后臺", "ws://129.204....:8887")};// 所有連接后臺//外網(wǎng)的自己放到服務(wù)器上
        etAddress.setText(serverInfos[0].serverAddress);// 默認(rèn)選擇第一個連接協(xié)議

        ArrayAdapter<ServerInfo> serverAdapter = new ArrayAdapter<ServerInfo>(this, android.R.layout
                .simple_spinner_item, serverInfos);
        spAddress.setAdapter(serverAdapter);
        spAddress.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

                ServerInfo selectServerInfo = (ServerInfo) spAddress.getItemAtPosition(position);// 選擇連接后臺
                etAddress.setText(selectServerInfo.serverAddress);

                etDetails.append("當(dāng)前連接后臺:" + selectServerInfo.serverName + "\n");

                Log.e("wlf", "當(dāng)前連接后臺:" + selectServerInfo.serverName);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                selectDraft = null;// 清空

                Log.e("wlf", "未選擇任何連接后臺");
            }
        });

        UserNameInfo[] loginNameInfo = {new UserNameInfo("老鄧", "老鄧"), new UserNameInfo("老鄭", "老鄭"),new UserNameInfo("小金魚", "小金魚"),
                new UserNameInfo("張三", "張三"),new UserNameInfo("李四", "李四"),new UserNameInfo("王二", "王二")};// 登錄對象
        etloginName.setText(loginNameInfo[0].name);// 默認(rèn)選擇第一個用戶登錄

        ArrayAdapter<UserNameInfo> loginNameAdapter = new ArrayAdapter<UserNameInfo>(this, android.R.layout
                .simple_spinner_item, loginNameInfo);
        sploginName.setAdapter(loginNameAdapter);
        sploginName.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

                UserNameInfo selectloginNameInfo = (UserNameInfo) sploginName.getItemAtPosition(position);// 選擇連接后臺
                etloginName.setText(selectloginNameInfo.name);

                etDetails.append("當(dāng)前登錄用戶名:" + selectloginNameInfo.loginName + "\n");

                Log.e("wlf", "當(dāng)前登錄用戶名:" + selectloginNameInfo.loginName);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                etloginName = null;// 清空

                Log.e("wlf", "未選任何登錄對象");
            }
        });

        UserNameInfo[] userNameInfo = {new UserNameInfo("all", "all"),new UserNameInfo("老鄧", "老鄧"), new UserNameInfo("老鄭", "老鄭"),new UserNameInfo("小金魚", "小金魚"),
                new UserNameInfo("李四", "李四"), new UserNameInfo("張三", "張三"), new UserNameInfo("王二", "王二")};// 要發(fā)送的對象

        ArrayAdapter<UserNameInfo> userNameAdapter = new ArrayAdapter<UserNameInfo>(this, android.R.layout
                .simple_spinner_item, userNameInfo);
        spName.setAdapter(userNameAdapter);
        spName.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

                UserNameInfo selectuserNameInfo = (UserNameInfo) spName.getItemAtPosition(position);// 選擇連接后臺
               // etName.setText(selectuserNameInfo.name);

                etDetails.append("發(fā)送對象:" + selectuserNameInfo.loginName + "\n");

                Log.e("wlf", "發(fā)送對象:" + selectuserNameInfo.loginName);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
               // etName = null;// 清空

                Log.e("wlf", "未選任何發(fā)送對象");
            }
        });

        btnConnect.setOnClickListener(this);
        btnClearDetails.setOnClickListener(this);
        btnClose.setOnClickListener(this);
        btnSend.setOnClickListener(this);

        WebSocketImpl.DEBUG = true;
        System.setProperty("java.net.preferIPv6Addresses", "false");
        System.setProperty("java.net.preferIPv4Stack", "true");
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btnConnect:
                try {
                    if (selectDraft == null) {
                        return;
                    }
                    if(etloginName == null){
                        return;
                    }
                    String address = etAddress.getText().toString().trim();
                    if (address.contains("JSR356-WebSocket")) {
                        //address += etName.getText().toString().trim();
                    }
                    Log.e("wlf", "連接地址:" + address);
                    client = new WebSocketClient(new URI(address), selectDraft.draft) {
                        @Override
                        public void onOpen(final ServerHandshake serverHandshakeData) {
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    etDetails.append("已經(jīng)連接到服務(wù)器【" + getURI() + "】\n");

                                    Log.e("wlf", "已經(jīng)連接到服務(wù)器【" + getURI() + "】");

                                    spDraft.setEnabled(false);
                                    etAddress.setEnabled(false);
                                    spAddress.setEnabled(false);
                                    etloginName.setEnabled(false);
                                    sploginName.setEnabled(false);

                                    btnConnect.setEnabled(false);
                                    //etName.setEnabled(false);

                                    spName.setEnabled(true);
                                    btnClearDetails.setEnabled(true);
                                    btnClose.setEnabled(true);
                                    btnSend.setEnabled(true);
                                }
                            });
                        }

                        @Override
                        public void onMessage(final String message) {
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    etDetails.append("獲取到服務(wù)器信息【" + message + "】\n");

                                    Log.e("wlf", "獲取到服務(wù)器信息【" + message + "】");
                                }
                            });
                        }

                        @Override
                        public void onClose(final int code, final String reason, final boolean remote) {
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    etDetails.append("斷開服務(wù)器連接【" + getURI() + ",狀態(tài)碼: " + code + "乡洼,斷開原因:" + reason +
                                            "】\n");

                                    Log.e("wlf", "斷開服務(wù)器連接【" + getURI() + "崇裁,狀態(tài)碼: " + code + ",斷開原因:" + reason + "】");

                                    spDraft.setEnabled(true);
                                    etAddress.setEnabled(true);
                                    spAddress.setEnabled(true);
                                    etloginName.setEnabled(true);
                                    sploginName.setEnabled(true);

                                    btnConnect.setEnabled(true);
                                    //etName.setEnabled(true);

                                    spName.setEnabled(false);
                                    btnClearDetails.setEnabled(true);
                                    btnClose.setEnabled(false);
                                    btnSend.setEnabled(false);
                                }
                            });
                        }

                        @Override
                        public void onError(final Exception e) {
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    etDetails.append("連接發(fā)生了異呈牵【異常原因:" + e + "】\n");

                                    Log.e("wlf", "連接發(fā)生了異嘲挝龋【異常原因:" + e + "】");

                                    spDraft.setEnabled(true);
                                    etAddress.setEnabled(true);
                                    btnConnect.setEnabled(true);
                                    //etName.setEnabled(true);

                                    btnClearDetails.setEnabled(false);
                                    btnClose.setEnabled(false);
                                    btnSend.setEnabled(false);
                                }
                            });
                        }
                    };
                    client.connect();
                    new Thread(){
                        @Override
                        public void run(){
                            super.run();
                            try {
                                Thread.sleep(200);
                                if (client != null) {
                                    client.send(etloginName.getText().toString().trim());
                                    svChat.post(new Runnable() {
                                        @Override
                                        public void run() {
                                            svChat.fullScroll(View.FOCUS_DOWN);
                                            etMessage.setText("");
                                            etMessage.requestFocus();
                                        }
                                    });
                                }
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }.start();

                } catch (Exception e) {
                    e.printStackTrace();
                }
                break;
            case R.id.btnClearDetails:
                if (etDetails.getText().toString() != null && etDetails.getText().length()>0) {
                    etDetails.setText("");
                }
                break;
            case R.id.btnClose:
                if (client != null) {
                    client.close();
                }
                break;
            case R.id.btnSend:
                try {
                    if (client != null) {
                        //client.send(etName.getText().toString().trim() + "說:" + etMessage.getText().toString().trim());
                        //client.send(etName.getText().toString().trim() +"@"+etMessage.getText().toString().trim());
                        client.send(spName.getSelectedItem().toString().trim() +"@"+etMessage.getText().toString().trim());
                        svChat.post(new Runnable() {
                            @Override
                            public void run() {
                                svChat.fullScroll(View.FOCUS_DOWN);
                                etMessage.setText("");
                                etMessage.requestFocus();
                            }
                        });
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                break;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (client != null) {
            client.close();
        }
    }

    private class DraftInfo {

        private final String draftName;
        private final Draft draft;

        public DraftInfo(String draftName, Draft draft) {
            this.draftName = draftName;
            this.draft = draft;
        }

        @Override
        public String toString() {
            return draftName;
        }
    }

    private class ServerInfo {

        private final String serverName;
        private final String serverAddress;

        public ServerInfo(String serverName, String serverAddress) {
            this.serverName = serverName;
            this.serverAddress = serverAddress;
        }

        @Override
        public String toString() {
            return serverName;
        }
    }

    private class UserNameInfo {

        private final String loginName;
        private final String name;

        public UserNameInfo(String loginName, String name) {
            this.loginName = loginName;
            this.name = name;
        }

        @Override
        public String toString() {
            return loginName;
        }
    }
}

現(xiàn)在就可以完成H5和Andorid通信啦

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市锹雏,隨后出現(xiàn)的幾起案子壳炎,更是在濱河造成了極大的恐慌,老刑警劉巖逼侦,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異腰耙,居然都是意外死亡榛丢,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門挺庞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來晰赞,“玉大人,你說我怎么就攤上這事选侨∫从悖” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵援制,是天一觀的道長戏挡。 經(jīng)常有香客問我,道長晨仑,這世上最難降的妖魔是什么褐墅? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮洪己,結(jié)果婚禮上妥凳,老公的妹妹穿的比我還像新娘。我一直安慰自己答捕,他們只是感情好逝钥,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著拱镐,像睡著了一般艘款。 火紅的嫁衣襯著肌膚如雪持际。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天磷箕,我揣著相機(jī)與錄音选酗,去河邊找鬼。 笑死岳枷,一個胖子當(dāng)著我的面吹牛芒填,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播空繁,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼殿衰,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了盛泡?” 一聲冷哼從身側(cè)響起闷祥,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎傲诵,沒想到半個月后凯砍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡拴竹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年悟衩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片栓拜。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡座泳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出幕与,到底是詐尸還是另有隱情挑势,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布啦鸣,位于F島的核電站潮饱,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏诫给。R本人自食惡果不足惜饼齿,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蝙搔。 院中可真熱鬧缕溉,春花似錦、人聲如沸吃型。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至枉层,卻和暖如春泉褐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鸟蜡。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工膜赃, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人揉忘。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓跳座,卻偏偏與公主長得像,于是被迫代替她去往敵國和親泣矛。 傳聞我的和親對象是個殘疾皇子疲眷,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355