Отправлять и получать по одному сокету

Я довольно новичок в Java-сокетах, и у меня возникают проблемы с использованием одного и того же сокета для отправки и получения данных.

Сервер находится на устройстве Android:

ServerSocket listenSocket = null; OutputStream dataOutStream = null; Socket socket = null; InputStream dataInputStream = null; // Listen System.out.println("Start listening"); try { listenSocket = new ServerSocket(4370); socket = listenSocket.accept(); System.out.println("Connection accepted"); dataInputStream = socket.getInputStream(); dataOutStream = socket.getOutputStream(); while (dataInputStream.read() != -1); } catch (IOException e) { e.printStackTrace(); close(listenSocket, socket); return; } // Answer System.out.println("Answering..."); byte[] answer = {(byte) 0x82, (byte) 0xf8, 0, 0}; try { dataOutStream.write(answer); } catch (IOException e) { e.printStackTrace(); close(listenSocket, socket); return; } close(listenSocket, socket); System.out.println("Finished"); 

Клиент работает на Linux-машине с Java 6:

  Socket socket = new Socket("192.168.1.33", 4370); OutputStream dataOutputStream = socket.getOutputStream(); InputStream dataInputStream = socket.getInputStream(); byte[] bufferOut = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; dataOutputStream.write(bufferOut); System.out.println("Sent"); while (dataInputStream.read() != -1); socket.close(); System.out.println("Finished"); 

Проблема здесь в том, что сервер застревает while (dataInputStream.read() != -1); линия. Похоже, клиент никогда не закрывает отправку.

Если я делаю dataOutputStream.close() в клиентской части (после написания, конечно), то он работает, но тогда клиент умирает while (dataInputStream.read() != -1); Говоря, что розетка закрыта.

Я хочу, чтобы весь сокет был открыт для большего обмена данными через этот же сокет, пока не будет отправлена ​​команда закрытия.

Я, очевидно, что-то неправильно делаю, какие-то идеи? Заранее спасибо!

Edit : Олаф показал встроенный способ реализовать сценарий запроса-ответа в вопросе.

Закрытие потока, полученного из сокета, также закрывает сокет ( см. Также ). С другой стороны, для InputStream, полученного из сокета, невозможно увидеть, были ли все данные отправлены до тех пор, пока поток / сокет открыт (возможно, Будьте больше бит на своем пути!). Двухсторонняя связь не может работать таким образом, если не используется пример Олафа. Это позволяет дождаться ответа сервера.

То, что вы можете сделать, это определить конечный сигнал самостоятельно (например, строку «END»), и любая сторона прослушивает, пока этот конечный сигнал не будет прочитан, а затем запишет. Но это связано с любыми другими проблемами, с которыми вы обязательно столкнетесь (что, если отправленный текст содержит конечный сигнал, что, если партнер умирает до отправки таймаутов?). смотрите также

Я попытался бы посмотреть на SOAP или RESTful сервисы, которые хорошо поддерживаются на Java (но я не знаю, насколько хорошо на Android). Как правило, существует множество библиотек, которые решают эти проблемы для вас и освобождают вас от низкоуровневых сетей. Он почти всегда окупается, чтобы использовать существующее решение.

Вы не закрываете гнездо или выходной поток. Вы выполняете shutdownOutput () на стороне клиента:

 ... dataOutputStream.write(bufferOut); System.out.println("Sent"); socket.shutdownOutput(); ... 

Это называется наполовину закрытым, так как оно закрывает только одно направление и оставляет другое направление открытым.

Попробуйте очистить OutputStream, выполнив dataOutStream.flush()

Intereting Posts
Android – получить текущее время без зависимости от часов устройства Вычислить меру измерения перед отображением Android 4.4 – Прозрачные статусные / навигационные полосы – fitsSystemWindows / clipToPadding не работают через транзакции фрагментов Socket.io – ReferenceError: io не определен Как настроить Appium на Mac OS для запуска автоматических тестов из классов JAVA на устройствах Android и iOS Обнаружить прямоугольник в изображении и нарисовать контур с использованием открытого cv в android Плавающие кнопки Android над представлением В чем разница между Extends Application и Extends Activity в Android? Очки для запоминания при тестировании приложения для Android Как использовать тот же макет для Android и iPhone с использованием Titanium? Как сделать расстояние между буквами в Android TextView? Android Studio 1.1.0 Ошибка синхронизации проекта Gradle Ошибка импорта проекта Gradle на OSX SetBackground vs setBackgroundDrawable (Android) Android Украинский язык Показать / скрыть DrawerLayout зависит от текущего фрагмента