全部产品
云市场

HTTP2 流通道

更新时间:2019-04-17 17:09:57

简介

HTTP 2 流通到 SDK 提供流式数据接入。在一个连接上可以建立多个流通道,使用完流通到需要关闭流通道。不同于视频流,该流通道较轻量级,可以快速打开关闭,适合较有限流数据传输,比如文件上传等。
1.建立和云端的连接;
2.打开一个流通道;
3.发送数据流,可以一次性发完也可以多次发送完;
4.发送方接收云端的响应,可以是一次响应完,也可以一直下推数据;
5.流使用完需要关闭;
6.不需要再使用 HTTP2 的时候需要关闭连接。

初始化

SDK 目前支持两种方式的流通道认证:设备接入认证、APP接入认证。IStreamSender 是 HTTP2 流通道接口类。如果当前Android设备作为设备三元组接入,选择 设备认证初始化,如果是作为一个应用只集成H2能力,则选择 APP接入初始化方式。

设备初始化

```javaLinkKitInitParams params = new LinkKitInitParams();params.deviceInfo = deviceInfo; // 参考 Demo// params.propertyValues = propertyValues; // 其他初始化参数// params.connectConfig = userData;

/**

  • 如果用户需要设置域名*/IoTH2Config ioTH2Config = new IoTH2Config();
    1. ioTH2Config.clientId = "client-id";
    2. ioTH2Config.endPoint = "https://10.125.15.223:9999";
    params.iotH2InitParams = ioTH2Config;// 执行linkkit 初始化// linkkit 初始化成功之后可以使用如果方式获取 IStreamSender实例IStreamSender client = LinkKit.getInstance().getH2StreamClient();```

APP 初始化

Profile 是 APP 认证方式初始化入口,作为设备的时候不需要走 APP 初始化。

  1. /**
  2. * replace url appKey appSecret
  3. * url = "https://"
  4. * signMethod = AuthSignMethod.SHA1.getMethod();
  5. */
  6. Profile profile = Profile.getAppKeyProfile("url", "appKey", new IAuthSign() {
  7. @Override
  8. public String getAuthSign(String signContent) {
  9. @Override
  10. public String getSignMethod() {
  11. return AuthSignMethod.SHA1.getMethod();// set bu user
  12. }
  13. // TODO by user
  14. // use appSecret to sign signContent and return signValue
  15. // hmacMd5Hex、hmacSha1Hex、hmacSha256Hex、hmacSha384Hex、hmacSha512Hex
  16. HmacUtils utils = new HmacUtils(HmacAlgorithms.HMAC_SHA_1, "appSecret");
  17. return new String(Hex.encodeHex(utils.hmac(signContent)));
  18. }
  19. });
  20. IStreamSender client = StreamSenderFactory.streamSender(profile);

流通道

建联

CompletableListener 是通用的异步回调接口。

```java// 有可能会抛出已建联、网络相关 exception// client 即初始化获得的 IStreamSender 实现实例client.connect(new CompletableListener() { @Override public void complete(Object o) { }

  1. @Override
  2. public void completeExceptionally(Throwable throwable) {
  3. }

}););

  1. <a name="t2vexk"></a>
  2. ## [](#t2vexk)打开流
  3. > ```java
  4. final Http2Request request = new Http2Request();
  5. // 添加请求参数
  6. // request.getHeaders().add("nothing", "ddd");
  7. client.openStream(serviceNme,
  8. request, new CompletableListener<Http2Response>() {
  9. @Override
  10. public void complete(Http2Response http2Response) {
  11. ALog.w(TAG, "open stream result: " + http2Response);
  12. // save dataStreamId of this stream
  13. if (http2Response != null) {
  14. dataStreamId = StreamUtil.getDataStreamId(http2Response.getHeaders());
  15. }
  16. }
  17. @Override
  18. public void completeExceptionally(Throwable throwable) {
  19. showToast("open Stream failed");
  20. Log.w(TAG, "completeExceptionally: ", throwable);
  21. dataStreamOpened.set(false);
  22. }
  23. });

发送流

发送流需要使用到 openStream 返回的云端的 dataStreamId,以及需要发送的数据。一次请求分多次发送可以有两种方式:一种是当做普通请求,每次发送header和部分数据,并设置endStream为true;一种是第一次发送 header+data,后续只发送data。
数据发送可以分为以下几种(具体和业务服务端实现的功能有关):

  • 一次请求,一次响应;类似 HTTP 1.1

  • 一次请求,多次响应;数据下推

  • 一次请求,分多次发送; |header+data | header+data| … 或 | header + data |+ data|+ data|+…

IDownStreamListener 是下推数据流的数据接收接口。

```javaHttp2Request request = new Http2Request();request.setContent(sendData.getBytes());// 如果数据要多次分多次上传,比如文件上传,需要先设置总的大小,然后分多次上传;// request.setEndOfStream(endOfStream);// request.getHeaders().set(“content-length”, String.valueOf(length));// dataStreamId openStream 云端返回的 dataStreamIdclient.sendStream(dataStreamId, request, new IDownStreamListener() { @Override public void onHeadersRead(String s, Http2Headers http2Headers, boolean b) { ALog.d(TAG, “onHeadersRead() called with: s = [“ + s + “], http2Headers = [“ + http2Headers + “], b = [“ + b + “]”); }

  1. @Override
  2. public void onDataRead(String s, byte[] bytes, boolean b) {
  3. ALog.d(TAG, "onDataRead() called with: s = [" + s + "], bytes = [" + new String(bytes) + "], b = [" + b + "]");
  4. }
  5. @Override
  6. public void onStreamError(String s, IOException e) {
  7. ALog.w(TAG, "onStreamError() called with: s = [" + s + "], e = [" + e + "]");
  8. }
  9. }, new CompletableListener<StreamWriteContext>() {
  10. @Override
  11. public void complete(StreamWriteContext streamWriteContext) {
  12. ALog.d(TAG, "complete() called with: streamWriteContext = [" + streamWriteContext + "]");
  13. }
  14. @Override
  15. public void completeExceptionally(Throwable throwable) {
  16. ALog.w(TAG, "completeExceptionally() called with: throwable = [" + throwable + "]");
  17. }
  18. });
  1. <a name="oc3ris"></a>
  2. ## [](#oc3ris)关闭流
  3. > ```java
  4. Http2Request request = new Http2Request();
  5. request.setEndOfStream(true);
  6. client.closeStream(dataStreamId, request, new CompletableListener<Http2Response>() {
  7. @Override
  8. public void complete(Http2Response http2Response) {
  9. ALog.d(TAG, "complete() called with: http2Response = [" + http2Response + "]");
  10. }
  11. @Override
  12. public void completeExceptionally(Throwable throwable) {
  13. ALog.d(TAG, "completeExceptionally() called with: throwable = [" + throwable + "]");
  14. }
  15. });

断连

```java// client 即初始化获得的 IStreamSender 实现实例client.disconnect(new CompletableListener() { @Override public void complete(Object o) { }

  1. @Override
  2. public void completeExceptionally(Throwable throwable) {
  3. }

});

  1. <a name="gl8txp"></a>
  2. ## [](#gl8txp)文件上传
  3. 文件上传基于流通道实现,在使用文件上传功能的时候需要先建联、打开流,并拿到 dataStreamId。filePath 是文件要上传的绝对路径,包含文件名。需要用户确保该文件具备访问的权限,以及动态申请了文件的读写权限。文件上传采用的是 |header + data| data| data |... 多次请求发送,只有第一个请求会带header。
  4. > ```java
  5. Http2Request request = new Http2Request();
  6. request.getHeaders().add("xxx", "xxx");
  7. client.upload(dataStreamId, filePath, request, new CompletableListener<Http2Response>() {
  8. @Override
  9. public void complete(Http2Response o) {
  10. ALog.d(TAG, "complete() called with: o = [" + o + "]");
  11. // upload success
  12. }
  13. @Override
  14. public void completeExceptionally(Throwable throwable) {
  15. ALog.w(TAG, "completeExceptionally() called with: throwable = [" + throwable + "]");
  16. // upload fail
  17. }
  18. });