Android socket или http

Использование сокетов в Android

Создано большое количество приложений как для Android, так и для других ОС, которые взаимодействуют друг с другом с помощью установления соединенией по сети. К таким приложениям относятся, например, мессенджеры социальных сетей WhatsApp, Viber. Как правило, для установления соединения между такими приложениями используются сокеты.

Сокет (socket) — это интерфейс, позволяющий связывать между собой программы различных устройств, находящихся в одной сети. Сокеты бывают двух типов: клиентский (Socket) и серверный (ServerSocket). Главное различие между ними связано с тем, что сервер «открывает» определенный порт на устройстве, «слушает» его и обрабатывает поступающие запросы, а клиент должен подключиться к этому серверу, зная его IP-адрес и порт. В Android сокеты для передачи данных используют по умолчанию протокол TCP/IP, важной особенностью которого является гарантированная доставка пакетов с данными от одного устройства до другого.

Особенности использования сокетов

Что важно знать при использовании сокетов в Android ?

  • соединения сокетов отключаются при переходе устройства в спящий режим;
  • чтобы не «рвать» соединение при наступлении спящего режима в устройстве можно использовать сервис;
  • для использования интернет-сети необходимо Android-приложению предоставить нужные права в манифесте.

Для определения прав в манифесте необходимо в файл AndroidManifest.xml добавить следующую строку :

Теперь android-приложения будет иметь доступ к сети.

Далее в статье рассмотрим пример клиент-серверного сокетного соединения с передачей сообщения. Функции клиента будет выполнять android-приложение. Серверное java-приложение выполним в IDE Eclipse с использованием пакета concurrent. В конце страницы можно скачать оба приложения.

Клиентский android-сокет

Интерфейс andriod-приложения представлен на следующем скриншоте. Форма приложения включает поле ввода текстового сообщения и кнопки установления соединения сервером, передачи сообщения и закрытия соединения.

Клиентское приложение создадим из двух классов : класс взаимодействия с серверным сокетом Connection и класс стандартной активности MainActivity.

Класс Connection

Класс взаимодействия с сервером Connection получает при создании (через конструктор) параметры подключения : host и port. Методы Connection вызываются из активности и выполняют следующие функции :

Метод Описание
openConnection Метод открытия сокета/соединения. Если сокет открыт, то он сначала закрывается.
closeConnection Метод закрытия сокета
sendData Метод отправки сообщения из активности.
finalize Метод освобождения ресурсов

Листинг Connection

Класс активности MainActivity

В активности MainActivity определены параметры сервера : host, port. Помните, что IP-адрес сервера для Вашего android-примера не может быть localhost (127.0.0.1), иначе Вы будете пытаться связаться с сервером внутри Andriod-системы. Кнопки интерфейса связаны с методами обращения к классу Connection. Кнопки отправки сообщения mBtnSend и закрытия соединения mBtnClose с сервером блокируются при старте приложения. После установления соединения с сервером доступ к кнопкам открывается.

Листинг активности

Методы управления сокетным соединением

Ниже представлены методы обработки событий, связанных с нажатием кнопок интерфейса. Обратите внимание, что подключение к серверу выполняется в отдельном потоке, а открытие доступа к кнопкам в основном потоке, для чего вызывается метод runOnUiThread. Для отправки сообщения серверу также создается отдельный поток.

Серверное приложение

Серверное приложение включает 2 класса : Server и ConnectionWorker. Серверный класс Server будет выполнять обработку взаимодействия с клиентом с использованием ConnectionWorker в отдельном потоке. Конструктор ConnectionWorker в качестве параметра получает объект типа Socket для чтения сообщений клиента из потока сокета.

Листинг ConnectionWorker

ConnectionWorker получает входной поток inputStream из клиентского сокета и читает сообщение. Если сообщение отсутствует, т.е. количество прочитанных байт равно -1, то это значит, что соединение разорвано, то клиентский сокет закрывается. При закрытии клиентского соединения входной поток сокета также закрывается.

Читайте также:  Real drift для android

Серверный класс

Серверный класс Server создадим с использованием многопоточного пакета util.concurrent. На странице описания сетевого пакета java.net и серверного ServerSocket был приведен пример серверного модуля с использованием обычного потока Thread, при работе с которым необходимо решать задачу его остановки : cтарый метод Thread.stop объявлен Deprecated и предан строжайшей анафеме, а безопасная инструкция Thread.interrupt безопасна, к сожалению, потому, что ровным счетом ничего не делает (отправляет сообщение потоку : «Пожалуйста, остановись»). Услышит ли данный призыв поток остается под вопросом – все зависит от разаработчика.

Чтобы иметь возможность остановить сервер «снаружи» в серверный класс Server включим 2 внутренних реализующих интерфейс Callable класса : CallableDelay и CallableServer. Класс CallableDelay будет функционировать определенное время, по истечении которого завершит свою работу и остановит 2-ой серверный поток взаимодействия с клиентами. В данном примере CallableDelay используется только для демонстрации остановки потока, организуемого пакетом util.concurrent.

Листинг CallableDelay

CallableDelay организует цикл с задержками. После завершения последнего цикла cycle поток завершает цикл, останавливает вторую задачу futureTask[1] и закрывает сокет. В консоль выводится соответствующее сообщение.

Листинг CallableServer

Конструктор CallableServer в качестве параметров получает значение открываемого порта для подключения клиентов. При старте (метод call) создается серверный сокет ServerSocket и поток переходит в режим ожидания соединения с клиентом. Остановить поток можно вызовом метода stopTask, либо завершением «задачи» типа FutureTask с данным потоком.

При подключении клиента метод serverSoket.accept возвращает сокет, который используется для создания объекта ConnectionWorker и его запуска в отдельном потоке. А сервер (поток) переходит к ожиданию следующего подключения.

В случае закрытия сокета (завершение внешней задачи FutureTask с данным потоком) будет вызвано исключение Exception, где выполняется проверка закрытия сокета; при положительном ответе основной цикл прерывается и поток завершает свою работу.

Листинг серверного класса Server

Cерверный класс Server создает два потоковых объекта (callable1, callable2), формирует из них две задачи futureTask и запускает задачи на выполнение методом execute исполнителя executor. После этого контролируется завершение выполнение обоих задач методом isTasksDone. При завершении выполнения обеих задач завершается также и цикл работы executor’а.

Два внутренних описанных выше класса (CallableDelay, CallableServer) не включены в листинг.

Источник

Использовать HTTP или Socket с Android

Мне приходится отправлять данные с телефона Android на сервер очень часто, скажем, каждые 100 мс (батарея не проблема). Я обсуждаю с самим собой, нормально ли использовать стандартное соединение с URL-адресом Java для этой цели или создать собственную реализацию собственного сокета с использованием SocketChannel. Я имею полный контроль над обоими конечными точками и свободно выбираю все, что хочу. Каковы плюсы и минусы каждого из этих методов? Любой другой подход? Обратите внимание, что я уже пробовал Google XMPP. Но выяснилось, что многие точки данных падают. Не получил от Google ответа об этом.

Обратите внимание, что надежность является первоочередной задачей. Я должен получить каждый образец в реальном времени, если, конечно, не существует какой-либо проблемы в самой радиосвязи. Укажите несколько указателей.

Соединение Socket TCP:

    (+) Надежная доставка из-за повторной передачи пакетов TCP.
    (-) Нестандартные порты/протокалы блокируются многими поставщиками мобильного Интернета.
    (-) Повторная передача пакетов может вызвать задержки и, следовательно, не в реальном времени.

Подключение Socket UDP

    (+) Если пакет проходит через него, он получает самую низкую задержку этих методов.
    (-) Нестандартные порты/протокалы блокируются многими поставщиками мобильного Интернета.
    (-) Неверная доставка, пакеты могут быть дублированы, усечены или опущены.

    (+) Многие пользователи могут использовать ваше приложение (многие мобильные интернет-провайдеры блокируют порты рядом с HTTP (80) и HTTPS (443) и используют глубокую проверку пакетов (для HTTP), чтобы убедиться, что протокол соблюден).
    Самый надежный из-за повторной передачи TCP и прокси.
    (-) Повторная передача пакетов TCP может вызывать задержки и, следовательно, не в реальном времени.
    (-) Прокси могут добавить дополнительные задержки, что приведет к еще меньшему времени реального времени.
Читайте также:  Голосовая система для андроид

Источник

Используйте HTTP или Socket с Android

Мне нужно отправлять данные с телефона Android на сервер, очень часто, каждые 100 мс (батарея не проблема). Я спорю сам с собой, можно ли использовать для этой цели стандартное URL-соединение Java или создать свою собственную реализацию сокета с помощью SocketChannel. Я полностью контролирую обе конечные точки и могу выбирать все, что захочу. Каковы плюсы и минусы каждого из этих методов? Любой другой подход? Обратите внимание, что я уже пробовал Google XMPP. Но обнаружил, что многие точки данных теряются. Не получил ответа от Google по этому поводу.

Обратите внимание, что надежность — это первоочередная задача. Я должен получать каждый образец в режиме реального времени, если, конечно, нет проблем с самой радиосвязью. Пожалуйста, дайте несколько указателей.

4 ответа

Я рассматривал различные варианты: http, xmpp, кастомную реализацию сокета . наконец я наткнулся на https://github.com/Gottox/socket.io-java-client . Сработало безболезненно. Я был готов к работе в кратчайшие сроки! Конечно, помогло то, что я использовал socket.io в более раннем проекте. Я никогда не думал, что для socket.io будет Java-клиент! Думаю, я задавал неправильные вопросы. Пока это решение работает очень хорошо. Я буду тестировать и размещать обновления, если таковые будут. Рассмотрите этот вариант, если вам нужно реализовать постоянную связь в реальном времени.

Соединение сокета TCP:

  • (+) Надежная доставка за счет повторной передачи TCP-пакетов.
  • (-) Нестандартные порты / протоколы блокируются многими провайдерами мобильного интернета
  • (-) Повторная передача пакета может вызывать задержки и, следовательно, не в реальном времени.

Соединение сокета UDP

  • (+) Если пакет приходит, он получен с наименьшей задержкой среди этих методов.
  • (-) Нестандартные порты / протоколы блокируются многими провайдерами мобильного интернета
  • (-) Доставка ненадежная, пакеты могут дублироваться, урезаться или отбрасываться.
  • (+) Многие пользователи могут использовать ваше приложение (многие провайдеры мобильного Интернета блокируют порты, кроме HTTP (80) и HTTPS (443), и используют глубокую проверку пакетов (для HTTP), чтобы убедиться, что протокол соблюдается).
  • Самый надежный из-за повторной передачи TCP и прокси.
  • (-) Повторная передача TCP-пакетов может вызывать задержки и, следовательно, не в реальном времени.
  • (-) Прокси-серверы могут добавлять дополнительные задержки, что делает его еще менее реальным.

Если вам приходится передавать данные довольно часто, имеет смысл использовать сокеты. Вы можете поддерживать соединение открытым в течение долгого времени, отправляя пакеты в одном и том же канале, и не тратить ресурсы на его повторное открытие при каждой передаче.

Источник

Простой клиент-сервер на Android (интернет-мессенджер)

Важно. Все написанное ниже не представляет собой какой либо ценности для профессионалов, но может служит полезным примером для начинающих Android разработчиков! В коде старался все действия комментировать и логировать.

Поехали. Многие мобильные приложения (и не только) используют архитектуру клиент-сервер. Общая схема, думаю, понятна.

Уделим внимание каждому элементу и отметим:

  • сервер — представляет собой некую программу, работающую на удаленном компьютере, и реализующую функционал «общения» с приложениями-клиентами (слушает запросы, распознает переданные параметры и значения, корректно отвечает на них);
  • клиент — в нашем случае, программа на мобильном устройстве, которая умеет формировать понятный серверу запрос и читать полученный ответ;
  • интерфейс взаимодействия — некий формат и способ передачи/получения запросов/ответов обеими сторонами.
Читайте также:  Netguard для андроид github

Неважно, как реализован любой из этих элементов, все они в любом случае присутствуют. Давайте реализуем примитивный сервер и Android клиент, работающий с ним. Как пример, будем использовать любой популярный мобильный интернет-мессенджер (Viber, ICQ), а приложение условно назовем «интернет-чат».

Схема взаимодействия следующая:

Клиент, установленный на устройстве А, посылает сообщение для клиента, установленного на устройстве Б. И наоборот. Сервер играет роль связующего звена между устройством А и Б… С, Д… и т.д. Также он играет роль «накопителя» сообщений, для их восстановления, на случай удаления на одном из клиентских устройств.

Для хранения сообщений используем SQL БД как на сервере, так и на устройствах-клиентах (в принципе, вся работа клиентов интернет-мессенджеров и сводится к постоянной синхронизации локальной и удаленной БД с сообщениями). Дополнительно, наш интернет-чат будет уметь стартовать вместе с запуском устройства и работать в фоне. Взаимодействие будет происходить путем HTTP запросов и JSON ответов.

Более логично, если синхронизация происходит через порт/сокет, это с одной стороны упрощает задачу (не нужно циклично слать HTTP запросы на проверку новых сообщений, достаточно проверять состояние прослушиваемого сокета), но с другой стороны, это усложняет создание серверной части приложения.

Делаем сервер

Для реализации «сервера», нам нужно зарегистрироваться на любом хостинге, который дает возможность работы с SQL и PHP.

Создаем пустую SQL БД, в ней создаем таблицу.

  1. author — автор сообщения;
  2. client — получатель сообщения;
  3. data — время и дата получения сообщения на сервере;
  4. text — сообщение.

В двух следующих файлах необходимо изменить переменные, содержащие данные для доступа к БД, на свои, полученные Вами при регистрации Вашего«сервера».

Структура запросов к api:

  • обязательный атрибут action — может быть равен select (сервер ответит списком записей из своей БД), insert (сервер добавить новую запись в свою БД), delete (сервер очистит свою БД)
  • если action=insert, нам нужно будет передать дополнительные параметры: author (кто написал сообщение), client (кому адресовано сообщение), text (сообщение)
  • action=select может содержать дополнительный параметр data, в этом случае ответ сервера содержит не все сообщения из БД, а только те, у которых время создания позднее переданного

Примеры:

  • chat.php?action=delete – удалит все записи на сервере
  • chat.php?action=insert&author=Jon&client=Smith&text=Hello — добавит на сервере новую запись: автор Jon, получатель Smith, содержание Hello
  • chat.php?action=select&data=151351333 — вернет все записи, полученные после переданного времени в long формате

Клиентская часть

Теперь структура Android приложения:

В фоне работает FoneService.java, который, в отдельном потоке, каждые 15 секунд делает запрос на сервер. Если ответ сервера содержит новые сообщения, FoneService.java записывает их в локальную БД и отправляет сообщение ChatActivity.java о необходимости обновить ListView, с сообщениями. ChatActivity.java (если она в этот момент открыта) получает сообщение и обновляет содержимое ListView из локальной БД.

Отправка нового сообщения из ChatActivity.java происходит сразу на сервер, минуя FoneService.java. При этом наше сообщение НЕ записывается в локальную БД! Там оно появится только после получения его назад в виде ответа сервера. Такую реализацию я использовал в связи с важным нюансом работы любого интернет-чата — обязательной группировкой сообщений по времени. Если не использовать группировку по времени, будет нарушена последовательность сообщений. Учитывая, что клиентские приложения просто физически не могут быть синхронизированы с точностью до миллисекунд, а возможно будут работать даже в разных часовых поясах, логичнее всего будет использовать время сервера. Так мы и делаем.

Создавая новое сообщение, мы передаем запросом на сервер: имя автора сообщения, имя получателя сообщения, текст сообщения. Получая эту запись назад, в виде ответа сервера, мы получаем то, что отправляли + четвертый параметр: время получения сообщения сервером.

Источник

Оцените статью