#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; } } } }
Комментариев нет:
Отправить комментарий