Страницы

Поиск по вопросам

воскресенье, 1 марта 2020 г.

Какова методология работы клиента с сервером на android

#java #android #сеть


Я работаю на .Net C#. Сейчас появилась необходимость мигрировать на android. И задача
в написании именно клиента, так как сервер на C# написан и работает на десктопе.  

На C# взаимодействие клиента с сервером выглядело достаточно логично: 

  connect = new MyConnect(address, port);   
  ....    
  connect.Send("select ......... ;");  // SQL запрос  
  Object obj = connect.Receive();      
  ....      


На Java коннект с сервером происходит только в отдельном потоке. Сразу вопрос: а
как мне в основном потоке указать что мне надо передать на сервер и как потом получить
ответ? Все примеры, которые я нагуглил, сначала пишут что-то на сервер, потом читают
ответ (это все в отдельном потоке) и закрываются. А если мне, в зависимости от ответа
сервера, надо отправить серверу другой запрос - надо снова открывать сокет? Вообщем,
честно, пока не понимаю, как работать с сетью, не убивая на передачу и чтение половину
времени и кода...
На Java я пытаюсь перейти в течении чуть больше недели, но при знакомстве с работой
в сети создается впечатление, что она заточена для написания чего-то типа чатов - отправил
сообщение, получил ответ, плюхнул на форму, ждем входного сообщения или своего исходящего.
В моем случае - инициатором общения с сервером является только клиент: запроc клиента
- ответ сервера - и все.    

Вкратце, задача состоит в написании приложений для терминалов сбора данных (ТСД).
Хилые возможности данных девайсов делают предпочтительной отправку запросов на сервер
 и получение от него уже готовых ответов, не используя локальную базу данных.
    


Ответы

Ответ 1



Мне кажется в вашем случае имеет смысл запустить Service в котором уже будет открыто соединение. И общатся с сервисом по средствам Broadcast. Таким образом вам не нужно закрывать соединение каждый раз.

Ответ 2



Используйте Retrofit 2 для работы с API пруф. А то что в другом потоке это нормально для Android, чтобы UI не ждал ответа сервера и не было сообщения ANR.

Ответ 3



Почему я решил ответить на свой же вопрос? Во-первых, потому, что принятый мною ответ оказался достаточно тяжеловесным. Все-таки, это не та задача, как мне кажется, для решения которой надо писать отдельную службу. Тем не менее, большое спасибо Anton111111 ! Во-вторых, потому, что многократный поиск в Google ответа так и не дал - все решения давались исключительно для общения приложения с веб-сайтами, а для работы терминала сбора данных с сервером базы данных по локальной сети не подходили. В конце концов, решил таки я свою проблему. Решается она посредством AsyncTask. Вот "выжимка" из класса для открытия и закрытия соединения, и для передачи и приема данных. Если кому-то пригодится - буду рад! Кодировка UTF_16 выбрана исключительно из-за особенностей моего внутреннего протокола - в начале каждого пакета передается количество байт в пакете. Кодировка UTF8 в моем случае не подходит. По сути, это первый мой код, потому прошу, не судите строго :) public class dbClient { private String chSet = "UTF_16LE"; private Socket mSocket = null; private int mPort = 11963; public boolean isConnected = false; public String strSend; public boolean isDone = false; public dbClient() {} public void openDB(String _user, String _ip, int _port) { mUser = _user; mIP = _ip; mPort = _port; try { AsyncOpenConnection at = new AsyncOpenConnection(); at.execute(); at.get(); isConnected = true; } catch (Exception e) { close(); } return; } public void send(String _str) { strSend = _str; try { AsyncSend at = new AsyncSend(); at.execute(); at.get(); } catch (Exception e) { close(); } return; } public boolean recv() { boolean ret = false; try { AsyncRecv at = new AsyncRecv(); at.execute(); at.get(); ret = true; } catch (Exception e) { close(); } return ret; } public void close() { isConnected = false; try { AsyncCloseConnection at = new AsyncCloseConnection(); at.execute(); at.get(); } catch (Exception e) { } return; } //---------------- Классы AsyncTask ----------------------- // Класс AsyncTaskOpenConnection class AsyncOpenConnection extends AsyncTask { @Override protected void onPreExecute() { super.onPreExecute(); isConnected = false; isDone = false; } @Override protected Boolean doInBackground(Void... params) { try { openConnection(); isConnected = true; isDone = true; } catch (Exception e) { e.printStackTrace(); } return isConnected; } @Override protected void onPostExecute(Boolean result) { super.onPostExecute(result); } } // Класс AsyncSend class AsyncSend extends AsyncTask { @Override protected void onPreExecute() { super.onPreExecute(); isDone = false; } @Override protected Boolean doInBackground(Void... params) { try { sendData(strSend.getBytes(chSet)); isDone = true; } catch (Exception e) { e.printStackTrace(); } return isDone; } @Override protected void onPostExecute(Boolean result) { super.onPostExecute(result); } } class AsyncRecv extends AsyncTask { @Override protected void onPreExecute() { super.onPreExecute(); isDone = false; } @Override protected Boolean doInBackground(Void... params) { try { recvData(); isDone = true; } catch (Exception e) { e.printStackTrace(); } return isDone; } @Override protected void onPostExecute(Boolean result) { super.onPostExecute(result); } } class AsyncCloseConnection extends AsyncTask { @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected Boolean doInBackground(Void... params) { try { closeConnection(); } catch (Exception e) { e.printStackTrace(); return false; } return true; } @Override protected void onPostExecute(Boolean result) { super.onPostExecute(result); } } public void sendData(byte[] data) throws Exception { if (mSocket == null || mSocket.isClosed()) { throw new Exception("Невозможно отправить данные. Сокет не создан или закрыт"); } try { /* Отправка данных */ mSocket.getOutputStream().write(data); mSocket.getOutputStream().flush(); } catch (IOException e) { throw new Exception("Невозможно отправить данные: " + e.getMessage()); } } public void recvData() throws Exception { byte[] buf = new byte[1024 * 8]; try { int cnt = mSocket.getInputStream().read(buf, 0); } catch (IOException e) { throw new Exception("Невозможно считать данные: " + e.getMessage()); } } private void openConnection() throws Exception { closeConnection(); try { mSocket = new Socket(mIP, mPort); } catch (IOException e) { throw new Exception("Невозможно создать сокет: " + e.getMessage()); } } private void closeConnection() { if (mSocket != null && !mSocket.isClosed()) { try { mSocket.close(); } catch (IOException e) { Log.e(LOG_TAG, "Невозможно закрыть сокет: " + e.getMessage()); } finally { mSocket = null; } } } }

Комментариев нет:

Отправить комментарий