Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Request in a QUIC way @shibuya.apk#28
Search
TakuSemba
September 27, 2018
Technology
1.2k
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.2k
Jetpack Compose
takusemba
3
3.7k
Protobuf in Kotlin
takusemba
2
2.1k
Single Activity with MVVM
takusemba
4
1.4k
KotlinConf Report @ca.kt#7
takusemba
2
510
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
650
Other Decks in Technology
See All in Technology
Account Factory for Terraformによる 標準化されたアカウント発行の自動化
pensuke628
0
120
人にやさしく、AIにやさしく、書き手を選ばないIaCのガードレール再考 / Rethinking IaC Guardrails for Humans and AI Alike
kohbis
5
1.8k
可視化から始めたAI駆動開発_ochi_ver1.01 / AI-Driven Development Starting with Visualization_ver1.01
yayoi_dd
0
110
OpenClawでAzure DevOpsのWiki更新を自動化する - クラウドAIだけでは届かない場所へ
yutakaosada
0
130
Confitura 2026
logico_jp
0
110
Claude Designがめちゃくちゃ便利なので使ってほしい
diggymo
0
170
雪かき部 #7 もう怖くない!SELECT文!
foursue
0
230
GitHub Agentic Workflows を触ってみる
htkym
2
880
[Kiro Meetup #7] Kiro Crew Dive Deep
konippi
0
430
スキルを作る、その前に!複数人で使われるスキルを 作るためのプロセス
junkifurukawa
1
120
PQC移行の今 -- IETF からみた現在地
satokan
4
700
データ品質を壊しながらSnowflakeのAIに分析させてみた
kawanago
0
320
Featured
See All Featured
Visualization
eitanlees
153
17k
Into the Great Unknown - MozCon
thekraken
41
2.7k
Embracing the Ebb and Flow
colly
88
5.2k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
35k
AI Search: Where Are We & What Can We Do About It?
aleyda
0
8k
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
5
750
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.6k
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.4k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2.2k
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.6k
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.6k
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.2k
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