Поток сокета зависает при использовании IOUtils.copy()
Я хочу отправить InputStream
содержащий XML от клиента к серверу. Указанный сервер манипулирует потоком XML, используя Streaming API for XML (StAX)
и отправляет его обратно клиенту.
Мне удается отправить XML на сервер, клиент получает ответ, но не выходит, потому что сервер никогда не заканчивает чтение InputStream
сформировать клиента. Но когда сервер просто выводит данные в System.out
вместо отправки чего-то чтение заканчивается...
редактировать я забыл упомянуть, что IOUtils.copy()
выполняется в двух отдельных потоках на клиенте.
Вот некоторый код, чтобы воспроизвести это, я заменил StAX
расставаться с IOUtils.copy()
на сервере.
сервер
ServerSocket serverSocket = new ServerSocket(port);
Socket clientSocket = serverSocket.accept();
InputStream in = clientSocket.getInputStream();
OutputStream out = clientSocket.getOutputStream();
IOUtils.copy(in, out);
клиент
Socket socket = new Socket(host, port);
FileInputStream fin = new FileInputStream(file);
OutputStream out = socket.getOutputStream();
IOUtils.copy(fin, out)
InputStream in = socket.getInputStream();
IOUtils.copy(in, System.out)
3 ответа
Вы должны очистить и закрыть InputStream и OutputStream. как это:
ServerSocket serverSocket = new ServerSocket(port);
Socket clientSocket = serverSocket.accept();
InputStream in = clientSocket.getInputStream();
OutputStream out = clientSocket.getOutputStream();
IOUtils.copy(in, out);
//add
out.flush();
in.close();
out.close;
Вы, вероятно, создаете тупик.
- Клиент - отправляет данные на сервер.
- Сервер - возвращает данные клиенту.
- Клиент - считывает данные (которые сервер вернул обратно)
Таким образом, пока клиент отправляет данные на сервер, сервер отправляет их обратно клиенту. Клиент не читает эти данные, он занят отправкой.
В какой-то момент буферы TCP заполняются, и сервер блокирует отправку большего количества данных клиенту. Это означает, что сервер блокируется при отправке данных, поэтому в конечном итоге буферы TCP на принимающей стороне сервера также заполняются, и клиент блокирует отправку данных. Поскольку клиент теперь блокируется при отправке, он никогда не попадет в ту часть, где он читает зацикленные данные, поэтому сервер никогда не будет разблокирован.
Если вы отправляете небольшой документ, это может не произойти, так как все данные помещаются в буферы, но как только вы заполните буферы, система заблокируется.
Вы должны мультиплексировать отправку / получение. Например, вы можете запустить поток на клиенте, который делает
InputStream in = socket.getInputStream();
IOUtils.copy(in, System.out)
Таким образом, прием может осуществляться параллельно с отправкой данных клиентом.
Или вы можете использовать 2 потока на стороне сервера. Один для получения данных, отправки данных для отправки в другой поток, выполняющий отправку (в этом случае вам придется создать внутреннюю очередь между потоками).
Насколько я помню IOUtils.copy()
не смывает и не закрывает поток. Кажется, ты не уравниваешь ни флеш, ни близость тоже. Попытайся. Я считаю, что это ваша проблема.