Поток сокета зависает при использовании IOUtils.copy () - PullRequest
2 голосов
/ 01 декабря 2010

Я хочу отправить InputStream, содержащий XML, от клиента на сервер.Указанный сервер управляет потоком XML, используя Streaming API for XML (StAX), и отправляет его обратно клиенту.

Мне удается отправить XML на сервер, клиент получает ответ, но не завершает работу, поскольку сервер никогда не завершает работучтение InputStream формы клиента.Но когда сервер просто выводит данные на System.out вместо отправки чего-либо, чтение заканчивается ...

edit Я забыл упомянуть, что 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 ]

4 голосов
/ 17 февраля 2013

Вы должны очистить и закрыть 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;
3 голосов
/ 01 декабря 2010

Вы, вероятно, создаете тупик.

  • Клиент - отправляет данные на сервер.
  • Сервер - возвращает данные клиенту.
  • Клиент - считывает данные (которые сервер вернул обратно)

Итак, пока клиент отправляет данные на сервер, сервер отправляет их обратно клиенту. Клиент не читает эти данные, он занят отправкой.

В какой-то момент буферы TCP заполняются, и сервер блокирует отправку дополнительных данных клиенту. Это означает, что сервер заблокирован при отправке данных, поэтому в конечном итоге буферы TCP на принимающей стороне сервера также заполняются, и клиент блокирует при отправке данных. Поскольку клиент теперь блокируется при отправке, он никогда не попадет в ту часть, где он читает зацикленные данные, поэтому сервер никогда не разблокирует.

Если вы отправляете небольшой документ, это может не произойти, поскольку все данные помещаются в буферы, но как только вы заполните буферы, система заблокируется.

Вы должны мультиплексировать отправку / получение. например Вы можете запустить поток на клиенте, который делает

InputStream in = socket.getInputStream();
IOUtils.copy(in, System.out)

Таким образом, прием может осуществляться параллельно с отправкой данных клиентом

Или вы можете использовать 2 потока на стороне сервера. Один для получения данных, отправки данных для отправки в другой поток, выполняющий отправку (в этом случае вам придется создать внутреннюю очередь между потоками).

1 голос
/ 01 декабря 2010

Насколько я помню IOUtils.copy() не сбрасывает и не закрывает поток. Похоже, вы не коллируете ни флеш, ни закрывайте тоже. Попытайся. Я считаю, что это ваша проблема.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...