PCLでHttpStream を作ってみた

13
PCLHttpStream を作ってみた 川崎 高志 @espresso3389

Transcript of PCLでHttpStream を作ってみた

Page 1: PCLでHttpStream を作ってみた

PCLでHttpStreamを作ってみた

川崎高志@espresso3389

Page 2: PCLでHttpStream を作ってみた

誰?

川崎高志クミナス株式会社 Cuminas Corporation

代表取締役社長

主に使っている言語:

C/C++ 70%

C# 20%

その他 10%

Page 3: PCLでHttpStream を作ってみた

HTTPStream

• HTTP 1.1 の Range Access

• うまく行けばランダムシークできる

•最悪でも普通のダウンロードと同じ

• PDF を読み込むときには、お尻から読み込む• 効率的なロードにはランダムアクセスが欠かせない!

Page 4: PCLでHttpStream を作ってみた

PCL Stream Class

• HttpClientがないよん

• Stream.Closeがないよん (IDisposable.Dispose使う)

• FileStreamとかないよん

Page 5: PCLでHttpStream を作ってみた

HttpClientがないよん

• Microsoft.Net.Http• Microsoft HTTP Client Libraries

https://www.nuget.org/packages/Microsoft.Net.Http

Page 6: PCLでHttpStream を作ってみた

Close がないよん

• IDisposable.Dispose使う• そもそも Stream.Closeなんていらんかったんやー

• Dispose(bool disposing) を実装すればOK

Page 7: PCLでHttpStream を作ってみた

FileStreamとかないよん

•諦める?• 引数としてプラットフォーム依存コードから Stream の形で貰う

• キャッシュとかは MemoryStream でお茶を濁す?• メモリ使用量が心配

• 再起動したらキャッシュが消える

• PCL Storage• https://pclstorage.codeplex.com/

• IFolder/IFile微妙にダサい/大げさすぎる

•自分で頑張る• DIとかでプラットフォーム毎のコードを抱え込む

Page 8: PCLでHttpStream を作ってみた

HttpStream

• Stream.Read発生時にデータを取得し始める

•長さの分からないリソースは、便宜的に 0xffffffffffffffff というサイズだとする

•内部的には適当なブロック単位での読み込み(64KB)

•非同期対応 (ReadAsync)

• Rangeアクセス出来ない場合には諦めて全部読み込む

Page 9: PCLでHttpStream を作ってみた

HttpStream : CacheStream

•汎用のストリームキャッシュの仕組み

• HttpStreamは CacheStreamを継承する

•二つのメソッドを実装する:abstract long GetStreamLengthOrDefault(long defValue);

abstract Task<Range> LoadAsync(

Stream stream,

Range rangeToLoad,

CancellationToken cancellationToken);

Page 10: PCLでHttpStream を作ってみた

ランダムシーク

public override async Task<int> ReadAsync(

byte[] buffer, int offset, int count,

CancellationToken cancellationToken);

protected abstract Task<Range> LoadAsync(

Stream stream,

Range rangeToLoad,

CancellationToken cancellationToken);

Page 11: PCLでHttpStream を作ってみた

ダウンロードした区間をRange型で記憶

public class Range : IComparable<Range>

{

public long Offset;

public long Length;

public int CompareTo(Range other)

{

return (int)(Offset - other.Offset);

}

}

Offset

Length

Page 12: PCLでHttpStream を作ってみた

ダウンロードした区間をRange型で記憶

List<Range> _ranges;

_ranges.BinarySearch(new Range(Position, Count));

Page 13: PCLでHttpStream を作ってみた

PCL ターゲット分からない