android集成websocket下载方式

时间:2022-12-17 22:18:42

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,下载完后唤醒,继续下载下一个文件。

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