Android的websocket的应用

近要做一个基于车载设备的应用设计,需要使用基于H5的mui跨平台框架为客户端,通过服务器,连接车载的Android中控设备。想了一下,觉得可以用websocket尝试一下。
开发环境:
服务器:idea+java+tomcat9.0
h5客户端:hbuilder
android客户端: eclipse+sdk4.2.2

1.websocket的基本概念

WebSocket用于在Web浏览器和服务器之间进行任意的双向数据传输的一种技术。WebSocket协议基于TCP协议实现,包含初始的握手过程,以及后续的多次数据帧双向传输过程。其目的是在WebSocket应用和WebSocket服务器进行频繁双向通信时,可以使服务器避免打开多个HTTP连接进行工作来节约资源,提高了工作效率和资源利用率。
在这里插入图片描述

WebSocket目前支持两种统一资源标志符ws和wss,类似于HTTP和HTTPS。
ps:客户端在请求连接服务器的时候,需要以ws或者wss开头

WebSocket 事件

事件       事件处理程      描述
open     ws.onopen      连接建立时触发
message  ws.onmessage   客户端接收服务端数据时触发
error    ws.onerror     通信发生错误时触发
close    ws.onclose     连接关闭时触发

WebSocket 方法

方法                  描述
ws.send()            使用连接发送数据
ws.close()           关闭链接

2.服务器搭建

在测试阶段,我们就保持若干设备在同一局域网即可,比如访问同一个wifi ε=(´ο`*)))唉
使用idea创建一个web项目,并且导入使用的包文件
在这里插入图片描述
创建一个servlet文件,添加注解 @ServerEndpoint(“/websocket”) ,其中"/websocket"为后续客户端请求连接的地址

import java.io.IOException;
import java.util.HashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;

/**
 * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
 * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
 */
@ServerEndpoint("/websocket")
public class WebSocketTest {
    //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;

    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
    private static CopyOnWriteArraySet<WebSocketTest> webSocketSet = new CopyOnWriteArraySet<WebSocketTest>();

    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;

    /**
     * 连接建立成功调用的方法
     * @param session  可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
     */
    @OnOpen
    public void onOpen(Session session){
        this.session = session;
        webSocketSet.add(this);     //加入set中
        addOnlineCount();           //在线数加1
        System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(){
        webSocketSet.remove(this);  //从set中删除
        subOnlineCount();           //在线数减1
        System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     * @param message 客户端发送过来的消息
     * @param session 可选的参数
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("来自客户端的消息:" + message);
        //群发消息
        for(WebSocketTest item: webSocketSet){
            try {
                item.sendMessage(message);
            } catch (IOException e) {
                e.printStackTrace();
                continue;
            }
        }
    }

    /**
     * 发生错误时调用
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error){
        System.out.println("发生错误");
        error.printStackTrace();
    }

    /**
     * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
     * @param message
     * @throws IOException
     */
    public void sendMessage(String message) throws IOException{
        this.session.getBasicRemote().sendText(message);
        //this.session.getAsyncRemote().sendText(message);
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketTest.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketTest.onlineCount--;
    }
}

运行tomcat,页面能够正常打开就完事了

3.H5客户端实现

由于websocket本身就是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议,所以在进行H5开发的时候不需要导入任何文件。因为后期需要将H5封装成APK,打算使用mui跨平台框架进行开发,所以在测试的时候选择通过HBuilder做H5客户端的开发

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
    <title></title>
    <script src="js/mui.min.js"></script>
    <link href="css/mui.min.css" rel="stylesheet"/>
    <script type="text/javascript" charset="utf-8">
      	mui.init();
    </script>
</head>
<body>
	<div class="mui-content">	
		Welcome<br/><input id="text" type="text"/>
		<button id="send">发送消息</button>
		<hr/>
		<button onclick="closeWebSocket()">关闭WebSocket连接</button>
		<hr/>
		<div id="message"></div>
	</div>
</body>
<script type="text/javascript">
    var websocket = null;
    //判断当前浏览器是否支持WebSocket
    if ('WebSocket' in window) {
        websocket = new WebSocket("ws://192.168.1.129:8080/websocket");
    }
    else {
        alert('当前浏览器 Not support websocket')
    }

    //连接发生错误的回调方法
    websocket.onerror = function () {
        setMessageInnerHTML("WebSocket连接发生错误");
    };

    //连接成功建立的回调方法
    websocket.onopen = function () {
        setMessageInnerHTML("WebSocket连接成功");
    }

    //接收到消息的回调方法
    websocket.onmessage = function (event) {
        setMessageInnerHTML(event.data);
    }

    //连接关闭的回调方法
    websocket.onclose = function () {
        setMessageInnerHTML("WebSocket连接关闭");
    }

    //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    window.onbeforeunload = function () {
        closeWebSocket();
    }

    //将消息显示在网页上
    function setMessageInnerHTML(innerHTML) {
        document.getElementById('message').innerHTML += innerHTML + '<br/>';
    }

    //关闭WebSocket连接
    function closeWebSocket() {
        websocket.close();
    }

    //发送消息
    function send() {
        var message = document.getElementById('text').value;
        websocket.send(message);
    }
	mui("#send")[0].addEventListener("tap",function(){
		websocket.send(mui("#text")[0].value);
	});
</script>
</html>

连接服务器后的效果如下
在这里插入图片描述
客户端输入文字
客户端效果
在这里插入图片描述
服务器效果
在这里插入图片描述

4.Android客户端的使用

前段时间因为项目需求研究了一下WebSocket与服务器端进行实时通讯的方式。WebSocket是html5中的一部分,但是在Android与服务器交互中使用是正常使用的,而且比socket的更易用。
由于车载设备系统Android版本较低,所以选择了eclipse进行开发
创建项目并且导入使用的包文件
在这里插入图片描述
还需要在AndroidManifest.xml中申请权限

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
package com.example.websocket;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;

import de.tavendo.autobahn.WebSocketConnection;
import de.tavendo.autobahn.WebSocketException;
import de.tavendo.autobahn.WebSocketHandler;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.StrictMode;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener {

	private static final String wsurl = "ws://192.168.1.129:8080/websocket";  
    private static final String TAG = "MainActivity";  
    private WebSocketConnection mConnect = new WebSocketConnection();  
    private EditText mContent;  
    private Button mSend;  
    private TextView mText;
    
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		//增加程序网络服务兼容性
        if(Build.VERSION.SDK_INT>9){
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }
        mContent = (EditText) findViewById(R.id.content);  
        mSend = (Button) findViewById(R.id.send);  
        mText = (TextView) findViewById(R.id.display);
        mSend.setOnClickListener(this);  
        connect(); 
    }
    
    /** 
     * websocket连接,接收服务器消息 
     */  
    private void connect() {  
        Log.i(TAG, "ws connect...."); 
        Toast.makeText(getApplicationContext(), "ws connect....", Toast.LENGTH_SHORT).show();
        try { 
            mConnect.connect(wsurl, new WebSocketHandler() {  
                @Override  
                public void onOpen() {  
                    Log.i(TAG, "Status:Connect to " + wsurl); 
                    Toast.makeText(getApplicationContext(), "Status:Connect to ", Toast.LENGTH_SHORT).show();  
                }  

                @Override  
                public void onTextMessage(String payload) {  
                    Log.i(TAG, payload);  
                    mText.setText(payload != null ? payload : "");  
//                    mConnect.sendTextMessage("I am android client");  
                    if(payload.equals("test")){
                    	mText.setText("进入测试模式");
                    }
                }  

                @Override  
                public void onClose(int code, String reason) {  
                    Log.i(TAG, "Connection lost..");
                    Toast.makeText(getApplicationContext(), "Connection lost..", Toast.LENGTH_SHORT).show();  
                }  
            });  
        } catch (WebSocketException e) {  
            e.printStackTrace();  
        }  
    }  

    /** 
     * 发送消息 
     * 
     * @param msg 
     */  
    private void sendMessage(String msg) {  
        if (mConnect.isConnected()) {  
            mConnect.sendTextMessage(msg);  
        } else {  
            Log.i(TAG, "no connection!!");  
            Toast.makeText(getApplicationContext(), "no connection!!", Toast.LENGTH_SHORT).show();  
        }  
    }  

    @Override  
    protected void onDestroy() {  
        super.onDestroy();  
        mConnect.disconnect();  
    }
    
	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		if (v == mSend) {  
            String content = mContent.getText().toString();  
            if (content != null && content.length() != 0)  
                sendMessage(content);  
            else  
                Toast.makeText(getApplicationContext(), "内容不能为空", Toast.LENGTH_SHORT).show();  
        }  
	}

}

连接服务器效果如下
在这里插入图片描述
在这里插入图片描述
客户端输入文字
Android客户端效果
在这里插入图片描述

服务器效果
在这里插入图片描述
h5客户端效果
在这里插入图片描述

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值