lundi 23 février 2015

OkHttp not multiplexing SPDY connections on Android 4.4.2



I am trying to do some experiment on Android and SPDY using OkHttp. However, I cannot get the multiplex feature of SPDY work on my Android phone. Below is my code.



private static final long WAIT_TIME = 1000 * 2; // Wait 2 seconds between each connection.
private static final long SIZE = 1000 * 1000 * 5; // Size of the content requested.

private static final String LOC = Environment.getExternalStorageDirectory().getPath();

private final static OkHttpClient mClient;
private final static OkUrlFactory mFactory;

static {
mClient = new OkHttpClient();
mClient.setConnectTimeout(5 * 60, TimeUnit.SECONDS);
mClient.setFollowRedirects(false);
mClient.setFollowSslRedirects(false);
mClient.setProxy(Proxy.NO_PROXY);
//mClient.setRetryOnConnectionFailure(false);
mFactory = new OkUrlFactory(mClient);
}

private void startOkHttp() {

for (int i = 0; i < 10; i++) {
final int idx = i;
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(idx);
try {
testOkHttpClient(LOC + "/" + idx);
} catch (IOException e) {
e.printStackTrace();
}
}
});
try {
Thread.sleep(WAIT_TIME);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.start();
}
}

private void testOkHttpClient(String fileLoc) throws IOException {

System.out.println("Multiplexing connections: " + ConnectionPool.getDefault().getMultiplexedConnectionCount());
System.out.println("getConnectionCount: " + ConnectionPool.getDefault().getConnectionCount());
System.out.println("getHttpConnectionCount: " + ConnectionPool.getDefault().getHttpConnectionCount());
System.out.println("getSpdyConnectionCount: " + ConnectionPool.getDefault().getSpdyConnectionCount());
Request request = new Request.Builder()
.url("https://the same url for all the connections")
.addHeader("Accept-Encoding", "gzip")
.addHeader("User-Agent", "com.google.android.youtube/10.05.6(Linux; U; Android 4.4.2; en_US; Nexus 5 Build/KOT49H)")
.addHeader("Range", "bytes=0-" + SIZE)
.addHeader("Connection", "keep-alive")
.build();

Response response = mClient.newCall(request).execute();

System.out.println("Status: " + response.code());

InputStream is = response.body().byteStream();
File file = new File(fileLoc);
if (!file.exists()) {
file.createNewFile();
}
FileOutputStream fos = new FileOutputStream(file);
ChannelUtils.fastChannelCopy(is, fos);
fos.close();
}


Basically it initiates a HTTP GET method to the same url (a video) every 2 seconds. What I was expecting was a single HTTPS connection and all 10 connections were multiplexed in it. However, what I found using wireshark is that there are 10 connections going to the same IP address. The good thing is that Wireshark tells me that each connections are using SPDY.


Wireshark output:


TLSv1.2 Record Layer: Application Data Protocol: spdy


The HTTPS connections are not reused since all connections started before any one finished downloading, which is reasonable.


The other thing is all the getMultiplexedConnectionCount(), getConnectionCount(), getHttpConnectionCount(), getSpdyConnectionCount() are giving me 0. I am so confused about it. As I read on the main page of okhttp, it should support SPDY with multiplexing. Could anyone tell me what I did wrong with the code? Or anyone can point out any other lib that I can use to do SPDY multiplexing on Android?


Thank you all for reading this!


Update: I am using a Android phone with Android 4.4.2, okhttp-2.2.0.


Update 2 response.protocol() returns me http/1.1, which is different from what I found in wireshark.


Follow up question:


With the above code, I successfully connect to https://www.google.ca and get spdy/3.1 with response.protocol(), which shows alpn is working fine. However when I tried to connect to http/2 enabled sites like http://ift.tt/1BIugo9 (it is a public http/2 test website), I am always getting http/1.1, not http/2 or something using the above code. In chrome, I can see that h2duo.cloudapp.net:443 with Protocol Negotiated:h2-14. I can see from okhttp code that I have h2-16 as one of the output of (OkHttpClient)mClient.getProtocols().


So why can't I connect to http://ift.tt/1BIugo9 with http/2?




Aucun commentaire:

Enregistrer un commentaire