Я довольно новичок в 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()