Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Request in a QUIC way @shibuya.apk#28
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
TakuSemba
September 27, 2018
Technology
1.1k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Request in a QUIC way @shibuya.apk#28
TakuSemba
September 27, 2018
More Decks by TakuSemba
See All by TakuSemba
Customize & Debug ExoPlayer @droidkaigi 2020
takusemba
0
2.1k
Jetpack Compose
takusemba
3
3.7k
Protobuf in Kotlin
takusemba
2
2k
Single Activity with MVVM
takusemba
4
1.4k
KotlinConf Report @ca.kt#7
takusemba
2
500
Lint for Kotlin @R.kt#3
takusemba
3
1.6k
Auto Release @potatochips#48
takusemba
1
1.3k
Media streaming on Android @droidkaigi 2018
takusemba
6
8.3k
gRPC on Android @DroidconSF Report
takusemba
1
640
Other Decks in Technology
See All in Technology
ruby.wasmとPicoRuby.wasmに対応した仮想DOMライブラリを作ってる話 #kaigieffect_kaigi
sue445
PRO
0
150
AI時代の開発生産性を捉え直す — 経営と現場をつなぐ「開発組織のオブザーバビリティ」— / AI Dev Ex Conference 2026
tkyowa
0
190
誤解だらけの開発生産性 / Myths and Misconceptions about Developer Productivity
i35_267
2
830
ファミコンでPHPを動かす / PHP on the Famicom
tomzoh
2
480
プロダクト開発組織の現在地(Ver.2026/07) / product-organization
kaonavi
0
120
Claude Code公式skillで 自分の仕事を少しずつ手放そう!(Claude Code開発ノウハウ大公開スペシャル by クラスメソッド)
kaym
1
510
副作用のある Lambda でも Lambda Power Tuning は使えるのか / lambda-power-tuning-side-effects
koukihosaka
1
120
Type-safe IaC for Dart
coborinai
0
160
LLM/Agent評価:トップ営業の発言を「正解」にする 〜暗黙的正解による評価を営業資産に変える〜
takkuhiro
1
230
Amplify Gen2でbackend.tsにCDKを定義する/しない事によるCDKの挙動の違いとユースケース
smt7174
1
430
「顧客の声を聞かなければ何も始まらない」 ── 顧客の声から生まれた『AI返信補助機能』の開発プロセス / AICon2026_shikata_imai
rakus_dev
0
140
AI時代のYAGNI:「爆速で無駄になった機能」からの学び / 20260720 Naoki Takahashi
shift_evolve
PRO
3
380
Featured
See All Featured
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
220
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
360
Rails Girls Zürich Keynote
gr2m
96
14k
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
260
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
2
1.5k
Darren the Foodie - Storyboard
khoart
PRO
3
3.4k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.5k
Making Projects Easy
brettharned
120
6.7k
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
460
Groundhog Day: Seeking Process in Gaming for Health
codingconduct
0
250
Accessibility Awareness
sabderemane
1
160
Transcript
None
@takusemba https://github.com/TakuSemba
QUIC?
Quick UDP Internet Connections
QUIC
Google QUIC https://www.chromium.org/quic
QUIC for IETF https://tools.ietf.org/html/draft-hamilton-early-deployment-quic-00
Merits
Merits ɾConnection establishment latency
Connection establishment latency Client Server
Connection establishment latency TCP Client Server
Connection establishment latency TCP Client Server
Connection establishment latency Client Server TCP + TLS
Connection establishment latency TCP + TLS Client Server
Connection establishment latency TCP + TLS Client Server 1-3 roundtrips
Connection establishment latency TCP + TLS Application Data Client Server
1-3 roundtrips
Connection establishment latency QUIC Client Server
Connection establishment latency QUIC Client Server
Connection establishment latency QUIC Client Server 0-1 roundtrips
Connection establishment latency QUIC Application Data Client Server 0-1 roundtrips
Merits ɾConnection establishment latency
Merits ɾConnection establishment latency ɾMultiplexing
Multiplexing TCP Client Server
Multiplexing TCP Client Server
Multiplexing TCP head of line blocking Client Server
Multiplexing QUIC stream 1 stream 2 stream 3 Client Server
Multiplexing QUIC stream 1 stream 2 stream 3 Client Server
Multiplexing QUIC … … stream 1 stream 2 stream 3
Client Server
Merits ɾConnection establishment latency ɾMultiplexing
Merits ɾConnection establishment latency ɾMultiplexing ɾConnection Migration
Connection Migration TCP IP: yyy.yyy.yyy.yyy Port: bb IP: xxx.xxx.xxx.xxx Port:
aa Client Server
Connection Migration TCP IP: yyy.yyy.yyy.yyy Port: bb IP: zzz.zzz.zzz.zzz Port:
cc Client Server
Connection Migration QUIC Connection ID: xxxxxx Connection ID: yyyyyy Client
Server
Connection Migration QUIC Connection ID: xxxxxx Connection ID: yyyyyy Client
Server
Merits ɾConnection establishment latency ɾMultiplexing ɾConnection Migration
Merits ɾConnection establishment latency ɾMultiplexing ɾConnection Migration ɾCongestion Control
Merits ɾConnection establishment latency ɾMultiplexing ɾConnection Migration ɾCongestion Control ɾForward
Error Correction
Cronet
https://developer.android.com/guide/topics/connectivity/cronet
Quicstart
dependencies { implementation "org.chromium.net:cronet-embedded:x.x.x" }
val cronetEngine = CronetEngine.Builder(context) .enableHttp2(true) .enableQuic(true) .build() val request =
cronetEngine.newUrlRequestBuilder(url, callback, executor) .setHttpMethod("GET") .addHeader("hoge", "huga") .build() request.start()
val cronetEngine = CronetEngine.Builder(context) .enableHttp2(true) .enableQuic(true) .build() val request =
cronetEngine.newUrlRequestBuilder(url, callback, executor) .setHttpMethod("GET") .addHeader("hoge", "huga") .build() request.start() .enableQuic(true)
val cronetEngine = CronetEngine.Builder(context) .enableHttp2(true) .enableQuic(true) .build() val request =
cronetEngine.newUrlRequestBuilder(url, callback, executor) .setHttpMethod("GET") .addHeader("hoge", "huga") .build() request.start()
val cronetEngine = CronetEngine.Builder(context) .enableHttp2(true) .enableQuic(true) .build() val request =
cronetEngine.newUrlRequestBuilder(url, callback, executor) .setHttpMethod("GET") .addHeader("hoge", "huga") .build() request.start() newUrlRequestBuilder(url, callback, executor)
val cronetEngine = CronetEngine.Builder(context) .enableHttp2(true) .enableQuic(true) .build() val request =
cronetEngine.newUrlRequestBuilder(url, callback, executor) .setHttpMethod("GET") .addHeader("hoge", "huga") .build() request.start() .setHttpMethod("GET") .addHeader("hoge", "huga")
val cronetEngine = CronetEngine.Builder(context) .enableHttp2(true) .enableQuic(true) .build() val request =
cronetEngine.newUrlRequestBuilder(url, callback, executor) .setHttpMethod("GET") .addHeader("hoge", "huga") .build() request.start()
val cronetEngine = CronetEngine.Builder(context) .enableHttp2(true) .enableQuic(true) .build() val request =
cronetEngine.newUrlRequestBuilder(url, callback, executor) .setHttpMethod("GET") .addHeader("hoge", "huga") .build() request.start()
val cronetEngine = CronetEngine.Builder(context) .enableHttp2(true) .enableQuic(true) .build() val request =
cronetEngine.newUrlRequestBuilder(url, callback, executor) .setHttpMethod("GET") .addHeader("hoge", "huga") .build() request.start() callback
val callback = object : UrlRequest.Callback() { private val bytesReceived
= ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onResponseStarted(request: UrlRequest, info: UrlResponseInfo) { // read response request.read(ByteBuffer.allocateDirect(32 * 1024)) } … }
val callback = object : UrlRequest.Callback() { private val bytesReceived
= ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onResponseStarted(request: UrlRequest, info: UrlResponseInfo) { // read response request.read(ByteBuffer.allocateDirect(32 * 1024)) } … } override fun onResponseStarted(request: UrlRequest, info: UrlResponseInfo) { // read response request.read(ByteBuffer.allocateDirect(32 * 1024)) }
val callback = object : UrlRequest.Callback() { private val bytesReceived
= ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) // read response byteBuffer.clear() request.read(byteBuffer) } … }
val callback = object : UrlRequest.Callback() { private val bytesReceived
= ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) // read response byteBuffer.clear() request.read(byteBuffer) } … } override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) // read response byteBuffer.clear() request.read(byteBuffer) }
val callback = object : UrlRequest.Callback() { private val bytesReceived
= ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) // read response byteBuffer.clear() request.read(byteBuffer) } … } override fun onReadCompleted( byteBuffer: ByteBuffer
val callback = object : UrlRequest.Callback() { private val bytesReceived
= ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) // read response byteBuffer.clear() request.read(byteBuffer) } … } private val receiveChannel = Channels.newChannel(bytesReceived) override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) }
val callback = object : UrlRequest.Callback() { private val bytesReceived
= ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) // read response byteBuffer.clear() request.read(byteBuffer) } … } override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // read response byteBuffer.clear() request.read(byteBuffer) }
val callback = object : UrlRequest.Callback() { private val bytesReceived
= ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) // read response byteBuffer.clear() request.read(byteBuffer) } … } override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) // read response byteBuffer.clear() request.read(byteBuffer) }
val callback = object : UrlRequest.Callback() { private val bytesReceived
= ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onSucceeded(request: UrlRequest, info: UrlResponseInfo) { // succeeded val result = bytesReceived.toByteArray() } … }
val callback = object : UrlRequest.Callback() { private val bytesReceived
= ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onSucceeded(request: UrlRequest, info: UrlResponseInfo) { // succeeded val result = bytesReceived.toByteArray() } … } override fun onSucceeded(request: UrlRequest, info: UrlResponseInfo) { // succeeded val result = bytesReceived.toByteArray() }
val callback = object : UrlRequest.Callback() { private val bytesReceived
= ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onFailed(request: UrlRequest, info: UrlResponseInfo, e: CronetException) { // failed Log.d("CRONET_SAMPLE", "failed: ${e.message}") } … } override fun onFailed(request: UrlRequest, info: UrlResponseInfo, e: CronetException) { // failed Log.d("CRONET_SAMPLE", "failed: ${e.message}") }
QUIC for ExoPlayer
https://github.com/google/ExoPlayer/tree/release-v2/extensions/cronet
Client .m3u8 .mp4 .mp4 .ts OkHttp
Client .m3u8 .mp4 .mp4 .ts Cronet
OkHttpClient
val userAgent = "takusemba" val okHttpClient = OkHttpClient() val transferListener
= DefaultBandwidthMeter() val factory = OkHttpDataSourceFactory(okHttpClient, userAgent, transferListener) OkHttpClient
val userAgent = "takusemba" val okHttpClient = OkHttpClient() val transferListener
= DefaultBandwidthMeter() val factory = OkHttpDataSourceFactory(okHttpClient, userAgent, transferListener) OkHttpClient Cronet
val userAgent = "takusemba" val okHttpClient = OkHttpClient() val transferListener
= DefaultBandwidthMeter() val factory = OkHttpDataSourceFactory(okHttpClient, userAgent, transferListener) OkHttpClient val userAgent = "takusemba" val cronetEngine = CronetEngine.Builder(context).enableQuic(true).build() val wrapper = CronetEngineWrapper(cronetEngine) val executor = Executors.newSingleThreadExecutor() val predicate = Predicate { contentType: String -> true } val factory = CronetDataSourceFactory(wrapper, executor, predicate, userAgent) Cronet
val userAgent = "takusemba" val okHttpClient = OkHttpClient() val transferListener
= DefaultBandwidthMeter() val factory = OkHttpDataSourceFactory(okHttpClient, userAgent, transferListener) OkHttpClient val userAgent = "takusemba" val cronetEngine = CronetEngine.Builder(context).enableQuic(true).build() val wrapper = CronetEngineWrapper(cronetEngine) val executor = Executors.newSingleThreadExecutor() val predicate = Predicate { contentType: String -> true } val factory = CronetDataSourceFactory(wrapper, executor, predicate, userAgent) val wrapper = CronetEngineWrapper(cronetEngine) val executor = Executors.newSingleThreadExecutor() val predicate = Predicate { contentType: String -> true } Cronet
val userAgent = "takusemba" val okHttpClient = OkHttpClient() val transferListener
= DefaultBandwidthMeter() val factory = OkHttpDataSourceFactory(okHttpClient, userAgent, transferListener) OkHttpClient Cronet val userAgent = "takusemba" val cronetEngine = CronetEngine.Builder(context).enableQuic(true).build() val wrapper = CronetEngineWrapper(cronetEngine) val executor = Executors.newSingleThreadExecutor() val predicate = Predicate { contentType: String -> true } val factory = CronetDataSourceFactory(wrapper, executor, predicate, userAgent) val factory = CronetDataSourceFactory(wrapper, executor, predicate, userAgent)
None
https://github.com/TakuSemba/QuicPlayer Sample App
https://github.com/takusemba https://twitter.com/takusemba Request in a QUIC way