ObjectInputStream.readObject () зависает навсегда во время процесса связи с сокетом - PullRequest
1 голос
/ 10 января 2012

Я столкнулся с проблемой связи через сокет в системе linux, процесс связи описан ниже: клиент отправляет сообщение, чтобы попросить сервер выполнить вычислительную задачу, и дождаться сообщения о результате от сервера после ее завершения.

Но клиент зависает, ожидая сообщения с результатом, если задача стоит долго, например, около 40 минут, хотя со стороны сервера сообщение с результатом было записано в сокет для ответа клиенту, но он обычно может получить сообщение о результате, если задача стоит немного времени, например, одна минута. Кроме того, эта проблема возникает только в пользовательской среде, процесс коммуникации в нашей тестовой среде работает нормально.

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

getSoTimeout:0
getReceiveBufferSize:43690
getSendBufferSize:8192
getSoLinger:-1
getTrafficClass:0
getKeepAlive:false
getTcpNoDelay:false

коды на CLient выглядят так:

Message msg = null;
ObjectInputStream in = client.getClient().getInputStream();
//if no message readObject() will hang here
while ( true ) {
  try {
   Object recObject = in.readObject();
   System.out.println("Client received msg.");
   msg = (Message)recObject; 
   return msg;
       }catch (Exception e) {
    e.printStackTrace();
    return null;
   }
}

коды на сервере похожи,

ObjectOutputStream socketOutStream = getSocketOutputStream();
try {
  MessageJobComplete msgJobComplete = new MessageJobComplete(reportFile, outputFile );
  socketOutStream.writeObject(msgJobComplete);
  }catch(Exception e) {
    e.printStackTrace();
  }

Для решения этой проблемы я добавил метод сброса и сброса, но проблема все еще существует:

ObjectOutputStream socketOutStream = getSocketOutputStream();
try {
   MessageJobComplete msgJobComplete = new MessageJobComplete(reportFile, outputFile );
   socketOutStream.flush();
   logger.debug("AbstractJob#reply to the socket");
   socketOutStream.writeObject(msgJobComplete);
   socketOutStream.reset();
   socketOutStream.flush();
   logger.debug("AbstractJob#after Flush Reply");
 }catch(Exception e) {
    e.printStackTrace();
            logger.error("Exception when sending MessageJobComplete."+e.getMessage());
 }

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

А в сокете, использующем протокол Tcp / Ip для связи, проблема связана с задачей с длительным временем, так что, какие значения о tcp повлияют на время ожидания сокета?

После анализа логов, обнаруженного после записи сообщения в сокет, исключений не было. Но всегда через 15 минут во фрагменте кода objectInputStream.readObject () на стороне сервера возникают исключения, которые используются для приема запроса от клиента. Однако значение socket.getSoTimeout равно 0, поэтому очень странно, что было сгенерировано исключение тайм-аута.

{2012-01-09  17:44:13,908} ERROR java.net.SocketException: Connection timed out
   at java.net.SocketInputStream.socketRead0(Native Method)
   at java.net.SocketInputStream.read(SocketInputStream.java:146)
   at sun.security.ssl.InputRecord.readFully(InputRecord.java:312)
   at sun.security.ssl.InputRecord.read(InputRecord.java:350)
   at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:809)
   at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:766)
   at sun.security.ssl.AppInputStream.read(AppInputStream.java:94)
   at sun.security.ssl.AppInputStream.read(AppInputStream.java:69)
   at java.io.ObjectInputStream$PeekInputStream.peek(ObjectInputStream.java:2265)
   at java.io.ObjectInputStream$BlockDataInputStream.peek(ObjectInputStream.java:2558)
   at  java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2568)
   at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1314)
   at java.io.ObjectInputStream.readObject(ObjectInputStream.java:368)

так почему генерируются исключения Тайм-аут соединения?

Ответы [ 2 ]

2 голосов
/ 09 февраля 2012

Эта проблема решена.используя tcpdump для захвата потоков сообщений.Я обнаружил, что в то время как на уровне приложения вызывался метод ObjectOutputStream.writeObject(), на уровне tcp много раз [TCP ReTransmission] было найдено.

Итак, я пришел к выводу, что соединение может быть разорвано, хотя с помощью команды netstat -an состояние соединения tcp все еще было ESTABLISHED.

Итак, я написал тестовое приложение, чтобы периодически отправлять тестовые сообщения в виде душераздирающих сообщений с Сервера.Тогда эта проблема исчезла.

1 голос
/ 10 января 2012

Методы read() для java.io.InputStream являются блокирующими вызовами. Это означает, что они ждут "вечно", если их вызывают, когда в потоке нет данных для чтения.

Это вполне ожидаемое поведение и согласно опубликованному контракту в javadoc, если сервер не отвечает.

Если вы хотите неблокирующее чтение, используйте классы java.nio.*.

...