106
Александр Зацепин разработчик, Мобильная почта/Почта [email protected]

Zacepin

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Zacepin

Александр Зацепин

р а з р а б о т ч и к , М о б и л ь н а я п о ч т а / П о ч т а

a l e x a n d e r . z a t s e p i n @ m a i l . r u

Page 2: Zacepin

Работа с сетью в Android

Page 3: Zacepin

0

100 000

200 000

300 000

400 000

500 000

600 000

700 000

800 000

2009 2010 2011 2012

Приложения

Page 4: Zacepin

Более 800000 приложений

Page 5: Zacepin

Server

Page 6: Zacepin
Page 7: Zacepin
Page 8: Zacepin
Page 9: Zacepin
Page 10: Zacepin

Сокеты

Client

Socket

Server

Server

Socket

Page 11: Zacepin

Частые опросы (Polling)

Server

Page 12: Zacepin

Длинные опросы (Long-Polling)

Server

Page 13: Zacepin

Пуш-нотификации

GCM

Server

Long-polling

App

subscribes

regId

System

Page 14: Zacepin

1. Сокеты

2. Длинные опросы (Long-polling)

3. Пуш-нотификации (Google Cloud Messaging(GCM))

4. Частые опросы сервера (Polling)

Виды возможных сетевых взаимодействий в Андроид

Page 15: Zacepin

1. Сокеты

2. Длинные опросы (Long-polling)

3. Пуш-нотификации (Google Cloud Messaging(GCM))

4. Частые опросы сервера (Polling)

Виды возможных сетевых взаимодействий в Андроид

Page 16: Zacepin

1. Сокеты

2. Длинные опросы (Long-polling)

3. Пуш-нотификации (Google Cloud Messaging(GCM))

4. Частые опросы сервера (Polling)

Виды возможных сетевых взаимодействий в Андроид

Page 17: Zacepin

HttpUrlConnection Server

Page 18: Zacepin

HttpUrlConnection Server

HttpContext

HttpClient

HttpRequest

HttpResponse

HttpEntity

HttpEntity

Server

Page 19: Zacepin

HttpUrlConnection connection = null; try { URL url = new URL("http://example.com"); connection = (HttpUrlConnection) url.openConnection();

Page 20: Zacepin

HttpUrlConnection connection = null; try { URL url = new URL("http://example.com"); connection = (HttpUrlConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setRequestProperty("Accept", "text/plain");

Page 21: Zacepin

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();

Page 22: Zacepin

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(); ...

Page 23: Zacepin

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(); } }

Page 24: Zacepin

try { HttpGet request = new HttpGet("http://example.com");

Page 25: Zacepin

try { HttpGet request = new HttpGet("http://example.com"); request.setHeader("Accept", "text/plain");

Page 26: Zacepin

try { HttpGet request = new HttpGet("http://example.com"); request.setHeader("Accept", "text/plain"); HttpResponse response = getHttpClient().execute(request);

Page 27: Zacepin

try { HttpGet request = new HttpGet("http://example.com"); request.setHeader("Accept", "text/plain"); HttpResponse response = getHttpClient().execute(request); int statusCode = response.getStatusLine().getStatusCode(); ...

Page 28: Zacepin

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(); }

Page 29: Zacepin

HttpUrlConnection Server

HttpContext

HttpClient

HttpRequest

HttpResponse

HttpEntity

HttpEntity

Server

Page 30: Zacepin

Server

HttpUrlConnection

HttpUrlConnection

HttpUrlConnection

App

Page 31: Zacepin

Server

Server

HttpUrlConnection

HttpUrlConnection

HttpUrlConnection

App

HttpContext

HttpClient

HttpRequest

HttpResponse

HttpEntity

HttpEntity

App

Page 32: Zacepin

Потокобезопасность

Thread N

1 2

HttpUrlConnection

Page 33: Zacepin

Потокобезопасность

Thread N

1 2

HttpUrlConnection

Page 34: Zacepin

Thread N

1 2

HttpClient

Потокобезопасность

Page 35: Zacepin

Thread N

1 2

HttpClient

ThreadSafeClientConnManager

. . .

connection 1

connection N

connection 2

1

2

Потокобезопасность

Page 36: Zacepin

Потокобезопасность static { ... HttpParams params = new BasicHttpParams(); ConnManagerParams.setMaxTotalConnections(params, 10);

Page 37: Zacepin

Потокобезопасность static { ... HttpParams params = new BasicHttpParams(); ConnManagerParams.setMaxTotalConnections(params, 10); ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRoute() { @Override public int getMaxForRoute(HttpRoute route) { return 5; } });

Page 38: Zacepin

Потокобезопасность 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); }

Page 39: Zacepin

Потокобезопасность 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); }

Page 40: Zacepin

Server

Application

request request ... request request

Page 41: Zacepin

Server

Application

request request ... request request

TCP TCP TCP TCP

Page 42: Zacepin

Server

Application

request request ... request request

TCP TCP TCP TCP + + …+… = traffic

Page 43: Zacepin

Keep-alive cоединение

Page 44: Zacepin

Keep-alive cоединение

Server

Application

request request ... request request

TCP

Page 45: Zacepin

Keep-alive cоединение

Server

Application

request request ... request request

TCP

+ …+… + = traffic

Page 46: Zacepin

Номер запроса

Время(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

Page 47: Zacepin

Номер запроса

Время(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

Page 48: Zacepin

Номер запроса

Время(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% быстрее!

Page 49: Zacepin

Keep Alive Duration

Page 50: Zacepin

Keep Alive Duration

𝐭

𝐭 − 𝐭𝐢𝐦𝐞

App

Page 51: Zacepin

Keep Alive Duration

𝐭

𝐭 − 𝐭𝐢𝐦𝐞

request1

App

Page 52: Zacepin

Keep Alive Duration

𝐭

𝐭 − 𝐭𝐢𝐦𝐞

request1

TCP

Server App

Page 53: Zacepin

Keep Alive Duration

𝐭

𝐭 − 𝐭𝐢𝐦𝐞

request1

request2 TCP

Server App

Page 54: Zacepin

Keep Alive Duration

𝐭

𝐭 − 𝐭𝐢𝐦𝐞

request1

request2

request3

TCP

Server App

Page 55: Zacepin

Keep Alive Duration

𝐭

𝐭 − 𝐭𝐢𝐦𝐞

request1

request2

request3

request4

TCP

Server App

Page 56: Zacepin

Keep Alive Duration

𝐭𝟑 > 𝐝

𝐭

𝐭 − 𝐭𝐢𝐦𝐞

𝐝 − 𝐤𝐞𝐞𝐩 𝐚𝐥𝐢𝐯𝐞 𝐝𝐮𝐫𝐚𝐭𝐢𝐨𝐧

request1

request2

request3

request4

TCP

Server App

Page 57: Zacepin

Keep Alive Duration

𝐭𝟑 > 𝐝

𝐭

𝐭 − 𝐭𝐢𝐦𝐞

𝐝 − 𝐤𝐞𝐞𝐩 𝐚𝐥𝐢𝐯𝐞 𝐝𝐮𝐫𝐚𝐭𝐢𝐨𝐧

request1

request2

request3

request4

TCP

TCP

Server App

Page 58: Zacepin

Keep Alive Duration

httpClient.setKeepAliveStrategy( new ConnectionKeepAliveStrategy() { @Override public long getKeepAliveDuration(HttpResponse response, HttpContext context){ return KEEP_ALIVE_DURATION_MILLISECONDS; } });

Page 59: Zacepin

Keep Alive Duration

Page 60: Zacepin

Keep Alive Duration

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO){ System.setProperty("http.keepAlive", "false"); }

Page 61: Zacepin

Keep Alive Duration

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO){ System.setProperty("http.keepAlive", "false"); }

Hе поддается настройке!(≈5 секунд)

Page 62: Zacepin

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(); } }

Page 63: Zacepin

Гзипование траффика

Page 64: Zacepin

Гзипование траффика ... InputStream is = response.getEntity().getContent(); Header contentEncoding = response.getFirstHeader("Content-Encoding");

Page 65: Zacepin

Гзипование траффика ... InputStream is = response.getEntity().getContent(); Header contentEncoding = response.getFirstHeader("Content-Encoding"); if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip"))

Page 66: Zacepin

Гзипование траффика ... InputStream is = response.getEntity().getContent(); Header contentEncoding = response.getFirstHeader("Content-Encoding"); if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) { is = new GZIPInputStream(is); } ...

Page 67: Zacepin

Гзипование траффика

... InputStream is = connection.getInputStream(); String contentEncoding = connection.getContentEncoding(); if ("gzip".equalsIgnoreCase(contentEncoding)) { is = new GZIPInputStream(connection.getInputStream()); } ...

Page 68: Zacepin

Гзипование траффика

Page 69: Zacepin

Гзипование траффика

Не полагайтесь на Content-Length!

Page 70: Zacepin

Управление куками

Page 71: Zacepin

Управление куками

Set-Cookie: name=value; expires=date; path=/; domain=.example.com

Page 72: Zacepin

Управление куками

... CookieStore cs = getHttpClient().getCookieStore(); BasicClientCookie c = new BasicClientCookie("Mpop", cookie); c.setDomain(".mail.ru"); cs.addCookie(c); ...

Page 73: Zacepin

Управление куками

... String cookieHeader = session.getCookieHeader(); сonnection.setRequestProperty("Cookie", cookieHeader); ...

Page 74: Zacepin

Установка куки в WebView Application

Page 75: Zacepin

Установка куки в WebView Application Browser

WebView

WebView

Page 76: Zacepin

Установка куки в WebView Application Browser

WebView

WebView

CookieSyncManager.createInstance(context);

Page 77: Zacepin

Установка куки в WebView Application Browser

WebView

WebView

CookieSyncManager.createInstance(context); CookieManager.getInstance().setAcceptCookie(true);

Page 78: Zacepin

Установка куки в WebView Application Browser

WebView

WebView

CookieSyncManager.createInstance(context); CookieManager.getInstance().setAcceptCookie(true); CookieManager.getInstance().setCookie("mail.ru",cookie);

Page 79: Zacepin

Установка куки в 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);

Page 80: Zacepin

Установка куки в 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();

Page 81: Zacepin

Установка куки в 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();

Page 82: Zacepin

Установка куки в 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();

Page 83: Zacepin

Защищенное соединение (https)

Page 84: Zacepin

Защищенное соединение (https)

CA

Application Server

Page 85: Zacepin

Защищенное соединение (https)

CA

Application Server

Signs certificate

Page 86: Zacepin

Защищенное соединение (https)

CA

Application Server

Signs certificate

request

Page 87: Zacepin

Защищенное соединение (https)

CA

Application Server

Signs certificate

Certificate

request

Private key

Public key

Page 88: Zacepin

Защищенное соединение (https)

CA

Application Server

Signs certificate

Certificate

request

Checks certificate

Private key

Public key

Page 89: Zacepin

Защищенное соединение (https)

CA

Application Server

Signs certificate

Certificate

request

Checks certificate

Random symmetric key

Private key

Public key

Page 90: Zacepin

Защищенное соединение (https)

CA

Application Server

Signs certificate

Certificate

request

Checks certificate

Random symmetric key

Data transferring

Private key

Public key

Page 91: Zacepin

1. KeyChain API на платформах >= 4.0

Варианты реализации https

Page 92: Zacepin

1. KeyChain API на платформах >= 4.0 2. На платформах < 4.0 надо создавать локальное хранилище ключей

Варианты реализации https

Page 93: Zacepin

1. KeyChain API на платформах >= 4.0 2. На платформах < 4.0 надо создавать локальное хранилище ключей

3. Доверять всем сертификатам

Варианты реализации https

Page 94: Zacepin

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()); ...

Page 95: Zacepin

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; }

Page 96: Zacepin

Доверять всем сертификатам

private class DummyHostnameVerifier implements HostnameVerifier{ @Override public boolean verify(String hostname, SSLSession session) { return true; } }

Page 97: Zacepin

Доверять всем сертификатам

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 } ... }

Page 98: Zacepin

Полезные инструменты

1. StrictMode 2. ConnectivityManager 3. DDMS Network Traffic Tool 4. Rest-client 5. Wireshark

Page 99: Zacepin

Полезные инструменты

1. StrictMode 2. ConnectivityManager 3. DDMS Network Traffic Tool 4. Rest-client 5. Wireshark

Page 100: Zacepin

Полезные инструменты

1. StrictMode 2. ConnectivityManager 3. DDMS Network Traffic Tool 4. Rest-client 5. Wireshark

Page 101: Zacepin

Полезные инструменты

1. StrictMode 2. ConnectivityManager 3. DDMS Network Traffic Tool 4. Rest-client 5. Wireshark

Page 102: Zacepin

Полезные инструменты

1. StrictMode 2. ConnectivityManager 3. DDMS Network Traffic Tool 4. Rest-client 5. Wireshark

Page 103: Zacepin

Полезные инструменты

1. StrictMode 2. ConnectivityManager 3. DDMS Network Traffic Tool 4. Rest-client 5. Wireshark

Page 104: Zacepin

Полезные ссылки

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

Page 105: Zacepin
Page 106: Zacepin

Александр Зацепин

р а з р а б о т ч и к , М о б и л ь н а я п о ч т а / П о ч т а

a l e x a n d e r . z a t s e p i n @ m a i l . r u