android集成websocket下载方式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/caonima0001112/article/details/50457282

http://www.zhihu.com/question/20215561 协议介绍可以看看这里。

下面稍微总结一下:

webstocket是html5的一种新的协议,它实现了浏览器与服务器的双向通道,使得数据可以快速的双向传播.

通过一次简单的握手,建立了客户端和服务器的联系后,服务器可以主动推送信息给客户端,而不需要客户端的反复请求。

一个websocket连接是客户端与服务器端在http协议的初始握手阶段将其升级到websocket协议来建立的,其底层还是tcp/ip连接。

优点:

客户端和服务器端之间数据交流的表头比较小。大概2个字节

服务器和客户端可以主动的发送数据给对方

不需要有频率的创建TCP请求和销毁,节约宽带和服务器的资源

需求下载流程

确定下载方式。当客户端确定下载方式为WebSocket方式时,客户端根据资源类型确定是同步或者异步方式下载离线资源,WebSocket需要支持异步下载和同步下载。

建立与服务器的连接。WebSocket初始化时,会根据“w”字段提供的Websockethost和服务端建立安全连接。连接失败两次,直接用http连接下载。

处理上送数据。WebSocket连接成功后,对上送的数据进行处理。处理方式同TCP。

发送数据到服务器。由于WebSocket通信是全双工通信的,确保更新下载,采用队列模式单文件下载,每次保证只有一个文件正在下载,只有当文件下载结束、超时或者取消下载的时候才会进行下一次的下载。

处理下载数据,对接收到得信息解析、组包、文件校验同TCP。

全部下载结束,断开连接,清空缓存。当所有文件下载完成后,客户端须主动断开WebSocket连接,并且清空相关缓存。如下载过程中连接断开,客户端须根据已成功下载的文件更新本地资源描述,并重新请求客户端更新接口。

我们基于开源框架autobahn开源框架来实现上诉需求。

首先介绍一下autobahn:

AutobahnAndroid 是 Android 平台上的 WebSocket & WAMP (WebSocket Application Messaging Protocol) 实现。

特点:

WebSocket 和 WAMP 客户端
实现了 WebSocket RFC6455, Draft Hybi-10+ and WAMP v1
支持 Android 2.2+
良好遵循标准
高性能异步设计
易用的 API
无缝集成 Android UI 应用
UI 线程上无网络 Activity

源码地址:https://github.com/qq451682583/autobahn-android/blob/master/Autobahn/src/de/tavendo/autobahn/WebSocketOptions.java

使用websocket首先创建所需实例:

mWebSocket = new WebSocketConnection();
mWSOptions = new WebSocketOptions();
// 设置最大下载文件大小(目前为5M)
mWSOptions.setMaxFramePayloadSize(5 * 1024 * 1024);

之后我们通过三个接口,即可完成链接,下载,关闭websocket。同时,根据需求我们要保证每次只能有一个文件下载,所以我们加入同步机制来实现。

public WebSocketDownload init() {

        try {
            mIsConnecting = true;

            mWebSocket.connect(mWS + Constants.OTA_WS, new WebSocketConnectionHandler() {

                @Override
                public void onOpen() {
                    Utils.printLog(Constants.OFF_TAG, "Status: connected to...");

                    mIsConnecting = false;

                    if (mIsDownloading) { // 服务器器重连成功,处理待请求的Model
                        mWebSocket.sendBinaryMessage(mBodys);
                    } else  {
                        notifyConnecting();
                    }
                }

                @Override
                public void onBinaryMessage(byte[] bytes) {

                    mBytes = handleResponse(bytes);
                    mIsDownloading = false; // 下载成功

                    notifyDownloading();
                }

                @Override
                public void onClose(int code, String reason) {
                    Utils.printLog(Constants.OFF_TAG, "Status: closed...[" + code + " : " + reason + "]");

                    mIsConnecting = false;

                    if (mIsDownloading) {// 若资源下载时需要重连,若主动断开不用重连
                        reconnectServer();
                    } else {
                        notifyConnecting();
                    }
                }

            }, mWSOptions);
            return this;
        } catch (WebSocketException e) {
            Utils.printLog(Constants.OFF_TAG, "Status: connect exception...");
            Utils.printException(e);
        }
        return null;
    }

/**
     * 叫醒等待连接的线程
     */
    private void notifyConnecting() {

        try {
            if (mWait != null) {
                // 叫醒等待连接的线程
                synchronized (mWait) {
                    mWait.notify();
                }
            }
        } catch (Exception e) {
            Utils.printException(e);
        }
    }

    /**
     * 叫醒等待下载的线程
     */
    private void notifyDownloading () {

        try {
            synchronized (mModel) {
                mModel.notify();
            }
        } catch (Exception e) {
            Utils.printException(e);
        }
    }
public void close() {
        try {
            if (mWebSocket != null && mWebSocket.isConnected()) {
                mWebSocket.disconnect();
            }
            mWebSocket = null;
        } catch (Exception e) {
            Utils.printException(e);
        }
    }
/**
     * 是否文件下载中
     * @return
     */
    public boolean isDownloading () {
        return mIsDownloading;
    }

    /**
     * 获取经过处理后的文件内容
     * 
     * @return
     */
    public byte[] getBytes() {
        return mBytes;
    }

    /**
     * 是否连接websocket 服务器中
     * @return
     */
    public boolean isConnecting () {
        return mIsConnecting;
    }

    /**
     * 是否websocket 已连接服务器
     * @return
     */
    public boolean isConnected () {
        return mWebSocket == null ? false : mWebSocket.isConnected();
    }
// 等待是否建立成功
            try {
                synchronized (wait) {
                    if (wsDownload.isConnecting()) {
                        Utils.printLog(Constants.OFF_TAG, "websocket wait connecting ...");
                        wait.wait();
                    }
                }
            } catch (InterruptedException e) {
                Utils.printException(e);
            }

// websocket 为异步下载
            if (download instanceof WebSocketDownload) {
                WebSocketDownload wsDownload = (WebSocketDownload)download;

                // 再判断是否文件下载中
                synchronized (model) {
                    if (wsDownload.isDownloading()) {
                        model.wait();
                    } 
                }

                bytes = wsDownload.getBytes();
            } 
//开启下载任务的时候,wait,等待链接成功,链接成功后开始下载,wait,下载完后唤醒,继续下载下一个文件。

本博文,只给出一个大致思路,旨为记录需求的解决。

猜你喜欢

转载自blog.csdn.net/caonima0001112/article/details/50457282