Upload
kuchinskaya
View
691
Download
0
Embed Size (px)
DESCRIPTION
Citation preview
Александр Зацепин
р а з р а б о т ч и к , М о б и л ь н а я п о ч т а / П о ч т а
a l e x a n d e r . z a t s e p i n @ m a i l . r u
Работа с сетью в Android
0
100 000
200 000
300 000
400 000
500 000
600 000
700 000
800 000
2009 2010 2011 2012
Приложения
Более 800000 приложений
Server
Сокеты
Client
Socket
Server
Server
Socket
Частые опросы (Polling)
Server
Длинные опросы (Long-Polling)
Server
Пуш-нотификации
GCM
Server
Long-polling
App
subscribes
regId
System
1. Сокеты
2. Длинные опросы (Long-polling)
3. Пуш-нотификации (Google Cloud Messaging(GCM))
4. Частые опросы сервера (Polling)
Виды возможных сетевых взаимодействий в Андроид
1. Сокеты
2. Длинные опросы (Long-polling)
3. Пуш-нотификации (Google Cloud Messaging(GCM))
4. Частые опросы сервера (Polling)
Виды возможных сетевых взаимодействий в Андроид
1. Сокеты
2. Длинные опросы (Long-polling)
3. Пуш-нотификации (Google Cloud Messaging(GCM))
4. Частые опросы сервера (Polling)
Виды возможных сетевых взаимодействий в Андроид
HttpUrlConnection Server
HttpUrlConnection Server
HttpContext
HttpClient
HttpRequest
HttpResponse
HttpEntity
HttpEntity
Server
HttpUrlConnection connection = null; try { URL url = new URL("http://example.com"); connection = (HttpUrlConnection) url.openConnection();
HttpUrlConnection connection = null; try { URL url = new URL("http://example.com"); connection = (HttpUrlConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setRequestProperty("Accept", "text/plain");
HttpUrlConnection connection = null; try { URL url = new URL("http://example.com"); connection = (HttpUrlConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setRequestProperty("Accept", "text/plain"); connection.connect();
HttpUrlConnection connection = null; try { URL url = new URL("http://example.com"); connection = (HttpUrlConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setRequestProperty("Accept", "text/plain"); connection.connect(); int statusCode = connection.getResponseCode(); ...
HttpUrlConnection connection = null; try { URL url = new URL("http://example.com"); connection = (HttpUrlConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setRequestProperty("Accept", "text/plain"); connection.connect(); int statusCode = connection.getResponseCode(); ... readTextFromServer(); } catch (Exception e) { e.printStackTrace(); } finally { if (connection != null) { connection.disconnect(); } }
try { HttpGet request = new HttpGet("http://example.com");
try { HttpGet request = new HttpGet("http://example.com"); request.setHeader("Accept", "text/plain");
try { HttpGet request = new HttpGet("http://example.com"); request.setHeader("Accept", "text/plain"); HttpResponse response = getHttpClient().execute(request);
try { HttpGet request = new HttpGet("http://example.com"); request.setHeader("Accept", "text/plain"); HttpResponse response = getHttpClient().execute(request); int statusCode = response.getStatusLine().getStatusCode(); ...
try { HttpGet request = new HttpGet("http://example.com"); request.setHeader("Accept", "text/plain"); HttpResponse response = getHttpClient().execute(request); int statusCode = response.getStatusLine().getStatusCode(); ... return EntityUtils.toString(response.getEntity()); } catch (Exception e) { e.printStackTrace(); }
HttpUrlConnection Server
HttpContext
HttpClient
HttpRequest
HttpResponse
HttpEntity
HttpEntity
Server
Server
HttpUrlConnection
HttpUrlConnection
HttpUrlConnection
…
App
Server
Server
HttpUrlConnection
HttpUrlConnection
HttpUrlConnection
…
App
HttpContext
HttpClient
HttpRequest
HttpResponse
HttpEntity
HttpEntity
App
Потокобезопасность
Thread N
1 2
HttpUrlConnection
Потокобезопасность
Thread N
1 2
HttpUrlConnection
Thread N
1 2
HttpClient
Потокобезопасность
Thread N
1 2
HttpClient
ThreadSafeClientConnManager
. . .
connection 1
connection N
connection 2
1
2
Потокобезопасность
Потокобезопасность static { ... HttpParams params = new BasicHttpParams(); ConnManagerParams.setMaxTotalConnections(params, 10);
Потокобезопасность static { ... HttpParams params = new BasicHttpParams(); ConnManagerParams.setMaxTotalConnections(params, 10); ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRoute() { @Override public int getMaxForRoute(HttpRoute route) { return 5; } });
Потокобезопасность static { ... HttpParams params = new BasicHttpParams(); ConnManagerParams.setMaxTotalConnections(params, 10); ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRoute() { @Override public int getMaxForRoute(HttpRoute route) { return 5; } }); ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(params, schemeRegistry); }
Потокобезопасность static { ... HttpParams params = new BasicHttpParams(); ConnManagerParams.setMaxTotalConnections(params, 10); ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRoute() { @Override public int getMaxForRoute(HttpRoute route) { return 5; } }); ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(params, schemeRegistry); httpClient = new DefaultHttpClient(cm, params); }
Server
Application
request request ... request request
Server
Application
request request ... request request
TCP TCP TCP TCP
Server
Application
request request ... request request
TCP TCP TCP TCP + + …+… = traffic
Keep-alive cоединение
Keep-alive cоединение
Server
Application
request request ... request request
TCP
Keep-alive cоединение
Server
Application
request request ... request request
TCP
+ …+… + = traffic
Номер запроса
Время(ms) KeepAlive = false
1 2098
2 2157
3 2037
4 2096
5 1944
6 2055
7 1865
8 2119
9 1986
10 1965
≈2032,2
Номер запроса
Время(ms) KeepAlive = false
Время(ms) KeepAlive = true
1 2098 2023
2 2157 1604
3 2037 1698
4 2096 1774
5 1944 1173
6 2055 1573
7 1865 1683
8 2119 1670
9 1986 1666
10 1965 1541
≈2032,2 ≈1700,5
Номер запроса
Время(ms) KeepAlive = false
Время(ms) KeepAlive = true
1 2098 2023
2 2157 1604
3 2037 1698
4 2096 1774
5 1944 1173
6 2055 1573
7 1865 1683
8 2119 1670
9 1986 1666
10 1965 1541
≈2032,2 ≈1700,5
На 16,2% быстрее!
Keep Alive Duration
Keep Alive Duration
𝐭
𝐭 − 𝐭𝐢𝐦𝐞
App
Keep Alive Duration
𝐭
𝐭 − 𝐭𝐢𝐦𝐞
request1
App
Keep Alive Duration
𝐭
𝐭 − 𝐭𝐢𝐦𝐞
request1
TCP
Server App
Keep Alive Duration
𝐭
𝐭 − 𝐭𝐢𝐦𝐞
request1
request2 TCP
Server App
Keep Alive Duration
𝐭
𝐭 − 𝐭𝐢𝐦𝐞
request1
request2
request3
TCP
Server App
Keep Alive Duration
𝐭
𝐭 − 𝐭𝐢𝐦𝐞
request1
request2
request3
request4
TCP
Server App
Keep Alive Duration
𝐭𝟑 > 𝐝
𝐭
𝐭 − 𝐭𝐢𝐦𝐞
𝐝 − 𝐤𝐞𝐞𝐩 𝐚𝐥𝐢𝐯𝐞 𝐝𝐮𝐫𝐚𝐭𝐢𝐨𝐧
request1
request2
request3
request4
TCP
Server App
Keep Alive Duration
𝐭𝟑 > 𝐝
𝐭
𝐭 − 𝐭𝐢𝐦𝐞
𝐝 − 𝐤𝐞𝐞𝐩 𝐚𝐥𝐢𝐯𝐞 𝐝𝐮𝐫𝐚𝐭𝐢𝐨𝐧
request1
request2
request3
request4
TCP
TCP
Server App
Keep Alive Duration
httpClient.setKeepAliveStrategy( new ConnectionKeepAliveStrategy() { @Override public long getKeepAliveDuration(HttpResponse response, HttpContext context){ return KEEP_ALIVE_DURATION_MILLISECONDS; } });
Keep Alive Duration
Keep Alive Duration
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO){ System.setProperty("http.keepAlive", "false"); }
Keep Alive Duration
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO){ System.setProperty("http.keepAlive", "false"); }
Hе поддается настройке!(≈5 секунд)
try { ... InputStream is = connection.getInputStream(); // Вычитывайте все данные из InputStream’a is.close(); } catch (Exception e) { try { InputStream es = connection.getErrorStream(); // Вычитывайте все данные из InputStream’a es.close(); } catch (Exception ex) { ex.printStackTrace(); } }
Гзипование траффика
Гзипование траффика ... InputStream is = response.getEntity().getContent(); Header contentEncoding = response.getFirstHeader("Content-Encoding");
Гзипование траффика ... InputStream is = response.getEntity().getContent(); Header contentEncoding = response.getFirstHeader("Content-Encoding"); if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip"))
Гзипование траффика ... InputStream is = response.getEntity().getContent(); Header contentEncoding = response.getFirstHeader("Content-Encoding"); if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) { is = new GZIPInputStream(is); } ...
Гзипование траффика
... InputStream is = connection.getInputStream(); String contentEncoding = connection.getContentEncoding(); if ("gzip".equalsIgnoreCase(contentEncoding)) { is = new GZIPInputStream(connection.getInputStream()); } ...
Гзипование траффика
Гзипование траффика
Не полагайтесь на Content-Length!
Управление куками
Управление куками
Set-Cookie: name=value; expires=date; path=/; domain=.example.com
Управление куками
... CookieStore cs = getHttpClient().getCookieStore(); BasicClientCookie c = new BasicClientCookie("Mpop", cookie); c.setDomain(".mail.ru"); cs.addCookie(c); ...
Управление куками
... String cookieHeader = session.getCookieHeader(); сonnection.setRequestProperty("Cookie", cookieHeader); ...
Установка куки в WebView Application
Установка куки в WebView Application Browser
WebView
WebView
Установка куки в WebView Application Browser
WebView
WebView
CookieSyncManager.createInstance(context);
Установка куки в WebView Application Browser
WebView
WebView
CookieSyncManager.createInstance(context); CookieManager.getInstance().setAcceptCookie(true);
Установка куки в WebView Application Browser
WebView
WebView
CookieSyncManager.createInstance(context); CookieManager.getInstance().setAcceptCookie(true); CookieManager.getInstance().setCookie("mail.ru",cookie);
Установка куки в WebView Application Browser
WebView
WebView
CookieSyncManager.createInstance(context); CookieManager.getInstance().setAcceptCookie(true); CookieManager.getInstance().setCookie("mail.ru",cookie); //for API level >= 15 CookieManager.getInstance().setCookie(".mail.ru",cookie);
Установка куки в WebView Application Browser
WebView
WebView
CookieSyncManager.createInstance(context); CookieManager.getInstance().setAcceptCookie(true); CookieManager.getInstance().setCookie("mail.ru",cookie); //for API level >= 15 CookieManager.getInstance().setCookie(".mail.ru",cookie) CookieSyncManager.getInstance().sync();
Установка куки в WebView Application Browser
WebView
WebView
cookie
cookie
CookieSyncManager.createInstance(context); CookieManager.getInstance().setAcceptCookie(true); CookieManager.getInstance().setCookie("mail.ru",cookie); //for API level >= 15 CookieManager.getInstance().setCookie(".mail.ru",cookie) CookieSyncManager.getInstance().sync();
Установка куки в WebView Application Browser
WebView
WebView
cookie
cookie
CookieSyncManager.createInstance(context); CookieManager.getInstance().setAcceptCookie(true); CookieManager.getInstance().setCookie("mail.ru",cookie); //for API level >= 15 CookieManager.getInstance().setCookie(".mail.ru",cookie) CookieSyncManager.getInstance().sync();
Защищенное соединение (https)
Защищенное соединение (https)
CA
Application Server
Защищенное соединение (https)
CA
Application Server
Signs certificate
Защищенное соединение (https)
CA
Application Server
Signs certificate
request
Защищенное соединение (https)
CA
Application Server
Signs certificate
Certificate
request
Private key
Public key
Защищенное соединение (https)
CA
Application Server
Signs certificate
Certificate
request
Checks certificate
Private key
Public key
Защищенное соединение (https)
CA
Application Server
Signs certificate
Certificate
request
Checks certificate
Random symmetric key
Private key
Public key
Защищенное соединение (https)
CA
Application Server
Signs certificate
Certificate
request
Checks certificate
Random symmetric key
Data transferring
Private key
Public key
1. KeyChain API на платформах >= 4.0
Варианты реализации https
1. KeyChain API на платформах >= 4.0 2. На платформах < 4.0 надо создавать локальное хранилище ключей
Варианты реализации https
1. KeyChain API на платформах >= 4.0 2. На платформах < 4.0 надо создавать локальное хранилище ключей
3. Доверять всем сертификатам
Варианты реализации https
Https на платформа < 4.0 ... TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm); KeyStore keyStore = KeyStore.getInstance("BKS"); InputStream in = context.getResources().openRawResource(mykeystore); keyStore.load(in, "mysecret".toCharArray()); in.close(); tmf.init(keyStore); SSLContext sslc = SSLContext.getInstance("TLS"); sslc.init(null, tmf.getTrustManagers(),new SecureRandom()); ...
Https на платформа < 4.0
private SSLSocketFactory createSslSocketFactory() { SSLSocketFactory sf = null; try { KeyStore keyStore = KeyStore.getInstance("BKS"); InputStream in = context.getResources().openRawResource(mykeystore); keyStore.load(in, "mysecret".toCharArray()); in.close(); sf = new SSLSocketFactory(keyStore); sf.setHostnameVerifier(STRICT_HOSTNAME_VERIFIER); } catch (Exception e) { e.printStackTrace(); } return sf; }
Доверять всем сертификатам
private class DummyHostnameVerifier implements HostnameVerifier{ @Override public boolean verify(String hostname, SSLSession session) { return true; } }
Доверять всем сертификатам
private class DummyTrustManager implements X509TrustManager{ @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { //empty } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { //empty } ... }
Полезные инструменты
1. StrictMode 2. ConnectivityManager 3. DDMS Network Traffic Tool 4. Rest-client 5. Wireshark
Полезные инструменты
1. StrictMode 2. ConnectivityManager 3. DDMS Network Traffic Tool 4. Rest-client 5. Wireshark
Полезные инструменты
1. StrictMode 2. ConnectivityManager 3. DDMS Network Traffic Tool 4. Rest-client 5. Wireshark
Полезные инструменты
1. StrictMode 2. ConnectivityManager 3. DDMS Network Traffic Tool 4. Rest-client 5. Wireshark
Полезные инструменты
1. StrictMode 2. ConnectivityManager 3. DDMS Network Traffic Tool 4. Rest-client 5. Wireshark
Полезные инструменты
1. StrictMode 2. ConnectivityManager 3. DDMS Network Traffic Tool 4. Rest-client 5. Wireshark
Полезные ссылки
1. KeyChain API – http://goo.gl/ICijf 2. Создание локального хранилища ключей – http://goo.gl/5Surx 3. Keep Alive - http://goo.gl/9cdlz 4. Минимизация расхода батареи - http://goo.gl/DML0m 5. Выполнение сетевых операций - http://goo.gl/GIVIs
Александр Зацепин
р а з р а б о т ч и к , М о б и л ь н а я п о ч т а / П о ч т а
a l e x a n d e r . z a t s e p i n @ m a i l . r u