详解OkSocket与Android的简单使用

一个Android轻量级Socket通讯框架,既OkHttp后又一力作.

框架开源地址: https://github.com/xuuhaoo/OkSocket,欢迎star,fork,Issue交流

OkSocket简介

Android OkSocket是一款基于阻塞式传统Socket的一款Socket客户端整体解决方案.您可以使用它进行简单的基于Tcp协议的Socket通讯,当然,也可以进行大数据量复杂的Socket通讯,
支持单工,双工通讯.

Maven配置

OkSocket 目前仅支持 JCenter 仓库

allprojects {
  repositories {
    jcenter()
  }
}

在Module的build.gradle文件中添加依赖配置

dependencies {
  compile 'com.tonystark.android:socket:1.0.0'
}

参数配置

在AndroidManifest.xml中添加权限:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

混淆配置

请避免混淆OkSocket,在Proguard混淆文件中增加以下配置:

-dontwarn com.xuhao.android.libsocket.**
-keep class com.xuhao.android.socket.impl.abilities.** { *; }
-keep class com.xuhao.android.socket.impl.exceptions.** { *; }
-keep class com.xuhao.android.socket.impl.EnvironmentalManager { *; }
-keep class com.xuhao.android.socket.impl.BlockConnectionManager { *; }
-keep class com.xuhao.android.socket.impl.UnBlockConnectionManager { *; }
-keep class com.xuhao.android.socket.impl.SocketActionHandler { *; }
-keep class com.xuhao.android.socket.impl.PulseManager { *; }
-keep class com.xuhao.android.socket.impl.ManagerHolder { *; }
-keep class com.xuhao.android.socket.interfaces.** { *; }
-keep class com.xuhao.android.socket.sdk.** { *; }
# 枚举类不能被混淆
-keepclassmembers enum * {
  public static **[] values();
  public static ** valueOf(java.lang.String);
}
-keep class com.xuhao.android.socket.sdk.OkSocketOptions$* {
  *;
}

OkSocket初始化

将以下代码复制到项目Application类onCreate()中,OkSocket会为自动检测环境并完成配置:

public class MyApplication extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    //在主进程初始化一次,多进程时需要区分主进程.
    OkSocket.initialize(this);
    //如果需要开启Socket调试日志,请配置
    //OkSocket.initialize(this,true);
  }
}

调用演示

测试服务器

该服务器是专门为初学者调试 OkSocket 库部属的一台测试服务器,初学者可以将项目中的 app 安装到手机上,点击 Connect 按钮即可,该服务器仅为熟悉通讯方式和解析方式使用.该服务器不支持心跳返回,不能作为商用服务器.服务器代码在 SocketServerDemo 文件夹中,请注意参考阅读.

IP: 104.238.184.237

Port: 8080

您也可以选择下载 JAR 文件到本地,运行在您的本地进行调试 Download JAR

下载后使用下面的代码将其运行起来java -jar SocketServerDemo.jar

简单的长连接

OkSocket 会默认对每一个 Open 的新通道做缓存管理,仅在第一次调用 Open 方法时创建 ConnectionManager 管理器,之后调用者可以通过获取到该ConnectionManager的引用,继续调用相关方法

ConnectionManager 主要负责该地址的套接字连接断开发送消息等操作.
//连接参数设置(IP,端口号),这也是一个连接的唯一标识,不同连接,该参数中的两个值至少有其一不一样
ConnectionInfo info = new ConnectionInfo("104.238.184.237", 8080);
//调用OkSocket,开启这次连接的通道,调用通道的连接方法进行连接.
OkSocket.open(info).connect();

有回调的长连接

注册该通道的监听器,每个 Connection 通道中的监听器互相隔离,因此如果一个项目连接了多个 Socket 连接需要在每个 Connection 注册自己的连接监听器,连接监听器是该 OkSocket 与用户交互的唯一途径

//连接参数设置(IP,端口号),这也是一个连接的唯一标识,不同连接,该参数中的两个值至少有其一不一样
ConnectionInfo info = new ConnectionInfo("104.238.184.237", 8080);
//调用OkSocket,开启这次连接的通道,拿到通道Manager
IConnectionManager manager = OkSocket.open(info);
//注册Socket行为监听器,SocketActionAdapter是回调的Simple类,其他回调方法请参阅类文档
manager.registerReceiver(new SocketActionAdapter(){
  @Override
  public void onSocketConnectionSuccess(Context context, ConnectionInfo info, String action) {
   Toast.makeText(context, "连接成功", LENGTH_SHORT).show();
  }
});
//调用通道进行连接
manager.connect();

可配置的长连接

获得 OkSocketOptions 的行为属于比较高级的 OkSocket 调用方法,每个 Connection 将会对应一个 OkSocketOptions,如果第一次调用 Open 时未指定 OkSocketOptions,OkSocket将会使用默认的配置对象,默认配置请见文档下方的高级调用说明

//连接参数设置(IP,端口号),这也是一个连接的唯一标识,不同连接,该参数中的两个值至少有其一不一样
ConnectionInfo info = new ConnectionInfo("104.238.184.237", 8080);
//调用OkSocket,开启这次连接的通道,拿到通道Manager
IConnectionManager manager = OkSocket.open(info);
//获得当前连接通道的参配对象
OkSocketOptions options= manager.getOption();
//基于当前参配对象构建一个参配建造者类
OkSocketOptions.Builder builder = new OkSocketOptions.Builder(options);
//修改参配设置(其他参配请参阅类文档)
builder.setSinglePackageBytes(size);
//建造一个新的参配对象并且付给通道
manager.option(builder.build());
//调用通道进行连接
manager.connect();

如何进行数据发送

//类A:
//...定义将要发送的数据结构体...
public class TestSendData implements ISendable {
  private String str = "";

  public TestSendData() {
    JSONObject jsonObject = new JSONObject();
    try {
      jsonObject.put("cmd", 14);
      jsonObject.put("data", "{x:2,y:1}");
      str = jsonObject.toString();
    } catch (JSONException e) {
      e.printStackTrace();
    }
  }

  @Override
  public byte[] parse() {
    //根据服务器的解析规则,构建byte数组
    byte[] body = str.getBytes(Charset.defaultCharset());
    ByteBuffer bb = ByteBuffer.allocate(4 + body.length);
    bb.order(ByteOrder.BIG_ENDIAN);
    bb.putInt(body.length);
    bb.put(body);
    return bb.array();
  }
}

//类B:
private IConnectionManager mManager;
//...省略连接及设置回调的代码...
@Override
public void onSocketConnectionSuccess(Context context, ConnectionInfo info, String action) {
   //连接成功其他操作...
   //链式编程调用
   OkSocket.open(info)
    .send(new TestSendData());

   //此处也可将ConnectManager保存成成员变量使用.
   mManager = OkSocket.open(info);
   if(mManager != null){
    mManager.send(new TestSendData());
   }
   //以上两种方法选择其一,成员变量的方式请注意判空
}

如何接收数据

OkSocket客户端接收服务器数据是要求一定格式的,客户端的OkSocketOptions提供了接口来修改默认的服务器返回的包头解析规则.请看下图为默认的包头包体解析规则

数据结构示意图

如上图包头中的内容为4个字节长度的int型,该int值标识了包体数据区的长度,这就是默认的头解析,如果需要自定义头请按照如下方法.

//设置自定义解析头
OkSocketOptions.Builder okOptionsBuilder = new OkSocketOptions.Builder(mOkOptions);
okOptionsBuilder.setHeaderProtocol(new IHeaderProtocol() {
  @Override
  public int getHeaderLength() {
    //返回自定义的包头长度,框架会解析该长度的包头
    return 0;
  }

  @Override
  public int getBodyLength(byte[] header, ByteOrder byteOrder) {
    //从header(包头数据)中解析出包体的长度,byteOrder是你在参配中配置的字节序,可以使用ByteBuffer比较方便解析
    return 0;
  }
});
//将新的修改后的参配设置给连接管理器
mManager.option(okOptionsBuilder.build());

//...正确设置解析头之后...
@Override
public void onSocketReadResponse(Context context, ConnectionInfo info, String action, OriginalData data) {
  //遵循以上规则,这个回调才可以正常收到服务器返回的数据,数据在OriginalData中,为byte[]数组,该数组数据已经处理过字节序问题,直接放入ByteBuffer中即可使用
}

如何保持心跳

//类A:
//...定义心跳管理器需要的心跳数据类型...
public class PulseData implements IPulseSendable {
  private String str = "pulse";

  @Override
  public byte[] parse() {
    byte[] body = str.getBytes(Charset.defaultCharset());
    ByteBuffer bb = ByteBuffer.allocate(4 + body.length);
    bb.order(ByteOrder.BIG_ENDIAN);
    bb.putInt(body.length);
    bb.put(body);
    return bb.array();
  }
}

//类B:
private IConnectionManager mManager;
private PulseData mPulseData = new PulseData;
//...省略连接及设置回调的代码...
@Override
public void onSocketConnectionSuccess(Context context, ConnectionInfo info, String action) {
   //连接成功其他操作...
   //链式编程调用,给心跳管理器设置心跳数据,一个连接只有一个心跳管理器,因此数据只用设置一次,如果断开请再次设置.
   OkSocket.open(info)
    .getPulseManager()
    .setPulseSendable(mPulseData)
    .pulse();//开始心跳,开始心跳后,心跳管理器会自动进行心跳触发

   //此处也可将ConnectManager保存成成员变量使用.
   mManager = OkSocket.open(info);
   if(mManager != null){
    PulseManager pulseManager = mManager.getPulseManager();
    //给心跳管理器设置心跳数据,一个连接只有一个心跳管理器,因此数据只用设置一次,如果断开请再次设置.
    pulseManager.setPulseSendable(mPulseData);
    //开始心跳,开始心跳后,心跳管理器会自动进行心跳触发
    pulseManager.pulse();
   }
   //以上两种方法选择其一,成员变量的方式请注意判空
}

心跳接收到了之后需要进行喂狗

因为我们的客户端需要知道服务器收到了此次心跳,因此服务器在收到心跳后需要进行应答,我们收到此次心跳应答后,需要进行本地的喂狗操作,否则当超过一定次数的心跳发送,未得到喂狗操作后,狗将会将此次连接断开重连.

//定义成员变量
private IConnectionManager mManager;
//当客户端收到消息后
@Override
public void onSocketReadResponse(Context context, ConnectionInfo info, String action, OriginalData data) {
  if(mManager != null && 是心跳返回包){//是否是心跳返回包,需要解析服务器返回的数据才可知道
    //喂狗操作
    mManager.getPulseManager().feed();
  }
}

如何手动触发一次心跳,在任何时间

//定义成员变量
private IConnectionManager mManager;
//...在任意地方...
mManager = OkSocket.open(info);
if(mManager != null){
  PulseManager pulseManager = mManager.getPulseManager();
  //手动触发一次心跳(主要用于一些需要手动控制触发时机的场景)
  pulseManager.trigger();
}

OkSocket参配选项及回调说明

OkSocketOptions

  1. Socket通讯模式mIOThreadMode
  2. 连接是否管理保存isConnectionHolden
  3. 写入字节序mWriteOrder
  4. 读取字节序mReadByteOrder
  5. 头字节协议mHeaderProtocol
  6. 发送单个数据包的总长度mSendSinglePackageBytes
  7. 单次读取的缓存字节长度mReadSingleTimeBufferBytes
  8. 脉搏频率间隔毫秒数mPulseFrequency
  9. 脉搏最大丢失次数(狗的失喂次数)mPulseFeedLoseTimes
  10. 后台存活时间(分钟)mBackgroundLiveMinute
  11. 连接超时时间(秒)mConnectTimeoutSecond
  12. 最大读取数据的兆数(MB)mMaxReadDataMB
  13. 重新连接管理器mReconnectionManager

ISocketActionListener

  1. Socket读写线程启动后回调onSocketIOThreadStart
  2. Socket读写线程关闭后回调onSocketIOThreadShutdown
  3. Socket连接状态由连接->断开回调onSocketDisconnection
  4. Socket连接成功回调onSocketConnectionSuccess
  5. Socket连接失败回调onSocketConnectionFailed
  6. Socket从服务器读取到字节回调onSocketReadResponse
  7. Socket写给服务器字节后回调onSocketWriteResponse
  8. 发送心跳后的回调onPulseSend
Copyright [2017] [徐昊]

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • android开发socket编程之udp发送实例分析

    本文实例讲述了android开发socket编程之udp发送实现方法.分享给大家供大家参考.具体分析如下: 需要实现的功能:采用udp下的socket编程,当按下确认键,模拟器发送文本框数据,pc机上的网络调试助手接收 一.环境: win7 + eclipse + sdk 二.代码: package test.soket; //import com.test_button.R; import java.io.DataOutputStream; import java.io.IOException

  • Android编程之客户端通过socket与服务器通信的方法

    本文实例讲述了Android编程之客户端通过socket与服务器通信的方法.分享给大家供大家参考,具体如下: 下面是一个demo,Android客户端通过socket与服务器通信. 由于Android里面可以完全使用java.io.*包和java.net.*包,那么,实际上,逻辑部分与J2SE没有区别.只是UI代码不一样. Android客户端通过socket与服务器通信分为下面5步: (1)通过IP地址和端口实例化Socket,请求连接服务器: 复制代码 代码如下: socket = new

  • python服务器与android客户端socket通信实例

    本文实例讲述了python服务器与android客户端socket通信的方法.分享给大家供大家参考.具体实现方法如下: 首先,服务器端使用python完成,下面为python代码: 复制代码 代码如下: #server.py  import socket  def getipaddrs(hostname):#只是为了显示IP,仅仅测试一下      result = socket.getaddrinfo(hostname, None, 0, socket.SOCK_STREAM)      re

  • Android中Socket通信的实现方法概述

    本文实例简述了Android中Socket通信的实现方法,具体内容如下: 一.socket通信概述 通俗的来说套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元.它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口. 应用层通过传输层进行数据通信时,TCP会遇到同时为多个应用程序进程提供并发服务的问题.多个TCP连接或多个应用程序进程可能需要通过同一个TCP

  • Android Socket通信详解

    一.Socket通信简介  Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是"请求-响应方式",即在请求时建立连接通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据.而Socket通信则是在双方建立起连接后就可以直接进行数据的传输,在连接时可实现信息的主动推送,而不需要每次由客户端想服务器发送请求. 那么,什么是socket?Socket又称套接字,在程序内部提供了与外界通信的端口,即端口通信.通过

  • Android NDK中socket的用法以及注意事项分析

    Android NDK中使用socket的整个过程分为以下几部分:第一部分: 创建socket并绑定IP和端口 复制代码 代码如下: #include <sys/select.h>#include <sys/socket.h>#include <arpa/inet.h>#define MAX_DATA_BUF_LEN 10240int sd = INVALID_SOCKET;sockaddr_in addr_org;  // 发送端地址sd = socket(AF_IN

  • Android中使用socket通信实现消息推送的方法详解

    原理 最近用socket写了一个消息推送的demo,在这里和大家分享一下. 主要实现了:一台手机向另外一台手机发送消息,这两台手机可以随时自由发送文本消息进行通信,类似我们常用的QQ. 效果图: 原理:手机通过socket发送消息到服务器,服务器每接收到一条消息之后,都会把这条消息放进一个messageList里面,服务器会不停地检测messageList是否含有消息,如果有的话就会根据messageList里面item的数据,推送到相应的另一端手机上面. 下面简单画了一个图来说明这个原理: 演

  • Android中使用WebSocket实现群聊和消息推送功能(不使用WebView)

    WebSocket protocol 是HTML5一种新的协议.它实现了浏览器与服务器全双工通信(full-duplex).WebSocket是Web2.0时代的新产物,用于弥补HTTP协议的某些不足,不过他们之间真实的关系是兄弟关系,都是对socket的进一步封装,其目前最直观的表现就是服务器推送和聊天功能.更多知识参考:如何理解 TCP/IP, SPDY, WebSocket 三者之间的关系? 今天的重点是讲如何在Android中脱离WebView使用WebSocket,而不是在Web浏览器

  • 详解OkSocket与Android的简单使用

    一个Android轻量级Socket通讯框架,既OkHttp后又一力作. 框架开源地址: https://github.com/xuuhaoo/OkSocket,欢迎star,fork,Issue交流 OkSocket简介 Android OkSocket是一款基于阻塞式传统Socket的一款Socket客户端整体解决方案.您可以使用它进行简单的基于Tcp协议的Socket通讯,当然,也可以进行大数据量复杂的Socket通讯, 支持单工,双工通讯. Maven配置 OkSocket 目前仅支持

  • 详解如何在Android studio中更新sdk版本和build-tools版本

    一.首先看下Android开发用到的sdk目录: build-tools 保存着一些Android平台相关通用工具,比如adb.和aapt.aidl.dx等文件.  aapt即Android Asset Packaging Tool , 在SDK的build-tools目录下. 该工具可以查看, 创建, 更新ZIP格式的文档附件(zip, jar, apk). 也可将资源文件编译成二进制文件.  Adb 即android debug bridge 管理模拟器和真机的万能工具,ddms 调试环境 

  • 详解Flutter 调用 Android Native 的方法

    Flutter 调用 Android Native 的方法,是通过MethodChannel的方式来实现的: 在Android端: 创建一个Class,实现FlutterPlugin和MethodCallHandler接口 重写onAttachedToEngine(),onDetachedFromEngine(),onMethodCall() onAttachedToEngine()中,根据自定义的CHANNEL_NAME创建MethodChannel, onDetachedFromEngine

  • 详解如何使用Android Studio 进行NDK开发和调试

    尽管Android Studio已经越来越流行了,但很多人还是习惯于Eclipse或源码环境下开发JNI应用.个人认为使用Android Studio作NDK开发是必然趋势,所以本文将简单介绍如何在Android Studio上实现NDK开发. 简介 JNI JNI 是Java Native Inteface的缩写,是Java中定义的一种用于连接Java和C/C++接口的一种实现方式. NDK NDK 是 Native Developmentit的缩写,是Google在Android开发中提供的

  • 详解如何在Android Studio中添加RecyclerView-v7支持包

    一直知道RecyclerView可以代替ListView.GridView使用,听说功能很强大,但还没有去学习过.今天想学习,没想到还没开始便撞墙了.输入Recycler,只有这两个东西,没有提示RecyclerView,说明支持包中没有. 最后一番百度后,终于解决(真不敢想象没有网络的情况下,怎么开发.怎么解决问题). 1.打开SDK Manager,在Extras树下找到Android Support Library,下载好支持包.RecyclerView在v7-21版本就出来了.我这里不用

  • android开发环境搭建详解(eclipse + android sdk)

    本开发环境为:eclipse + android sdk,步骤说明的顺序,没有特别要求,看个人爱好了 步骤说明: 1.安装eclipse 2.配置jdk 3.安装android sdk 4.安装ADT,关联eclipse和android 详细说明: 1.安装eclipse * 到官方网下载eclipse(http://www.eclipse.org/downloads/),我是下载的Eclipse IDE for Java EE Developers. * 正常解压安装,注意记得路径就可以了 2

  • 详解Dagger2在Android开发中的新用法

    本文假设读者已经有一定Dagger2使用经验 使用疑惑 之前工作中一直在使用dagger2进行开发,用起来确实很爽,但是我从我第一次使用我就一直有一个问题或者说疑问(本人才疏学浅脑子不够使),通常情况下我们有如下清单 MyApplication,MyAppComponent,MyAppModule ActActivity,ActComponent,ActModule 简单解释下,MyAppModule提供全局单例功能,比如打印日志,ActModule提供Activity级别的功能比如发起网络请求

  • 详解如何在Android中实现悬浮Activity

    通常来说,为一款已经优化过的手机APP开发平板的版本也不是很难.使用Fragment.decompose Entities等组件就可以又快又轻松地完成.但是,最近遇到一个项目就没有这么简单了.我们不只要开发一个平板APP(基于ActionBarSherlock库,也称作ABS),还需要实现以下功能: 实现一个悬浮并且透明显示的Activity,这样用户在进行输入操作的时候可以看到别的Activity或者它自己的窗口背景: 保存悬浮的Activity的原始尺寸,包括水平方向和竖直方向:最好是Act

  • 详解如何使用Android Studio开发Gradle插件

    缘由 首先说明一下为什么会有这篇文章.前段时间,插件化以及热修复的技术很热,Nuwa热修复的工具NuwaGradle,携程动态加载技术DynamicAPK,还有希望做最轻巧的插件化框架的Small.这三个App有一个共同的地方就是大量的使用了Gradle这个强大的构建工具,除了携程的框架外,另外两个都发布了独立的Gradle插件提供自动化构建插件,或者生成热修复的补丁.所以学习一下Gradle插件的编写还是一件十分有意义的事. 插件类型 Gradle的插件一般有这么几种: 一种是直接在项目中的g

  • 详解mac python+selenium+Chrome 简单案例

    第一步:下载selenium pip install selenium 第二步:下载和你当前谷歌浏览器对应的驱动Chromedriver 下载地址:https://npm.taobao.org/mirrors/chromedriver 这是我谷歌对应的版本,点击选择下载对应的系统文件,下载完解压到你项目的目录里即可! 第三步:简单操作selenium from selenium import webdriver import time # 创建Chrome的驱动对象 driver = webdr

随机推荐