Zacepin

Preview:

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