Java套接字超时不起作用(Java socket time out does not work)

我有一个类负责监听两个具有完全相同类的其他机器,所以它是由三台具有相同代码的计算机组成的网络。 连接在那里,我可以看到他们将数据传递给对方。 一切都工作正常。

当我拿出其中一台机器并观察其他两台机器的行为时,事情会变得棘手。 预计当其中一台机器由于某种原因停止工作时,另外两台机器应该继续工作。 如果他们中的两个停下来,剩下的就应该继续。

我试图在下面实现这个机制。 但是,当我拿出其中一台机器时,程序一直在等待,所以它不会切换到“双向比较模式”。

public void listen() { try { logger.info("Creating listener sockets"); while (isRunning) { final byte[] buf = new byte[bufferSize]; final DatagramPacket packetOne = new DatagramPacket(buf, buf.length); final DatagramPacket packetTwo = new DatagramPacket(buf, buf.length); MediatorMessageMsg mediatorMessageOne = null; MediatorMessageMsg mediatorMessageTwo = null; try { socketReceiverOne.receive(packetOne); ByteArrayInputStream firstInput = new ByteArrayInputStream(buf); mediatorMessageOne = MediatorMessageMsg.parseDelimitedFrom(firstInput); socketReceiverTwo.receive(packetTwo); ByteArrayInputStream secondInput = new ByteArrayInputStream(buf); mediatorMessageTwo = MediatorMessageMsg.parseDelimitedFrom(secondInput); logger.trace("Received packets"); } catch (final SocketTimeoutException e) { logger.trace(e.getMessage()); continue; } catch (final SocketException e) { logger.warn(e); logger.warn("Ignore the error and go on."); continue; } catch (final IOException e) { logger.error("Incoming communication stopped!"); logger.error(e); stop(); } // if two mediators sent the data, it's OK if (packetOne.getLength() > 0 && packetTwo.getLength() > 0) { handlePackets(mediatorMessageOne, mediatorMessageTwo); logger.info("Number of active mediators: 2. Comparison style: 1v1v1"); } // if only one sent the data, compare it with our own else if (packetOne.getLength() > 0 || packetTwo.getLength() > 0) { // whicehever sent the data, compare its data with our own logger.info("Number of active mediators: 1. Comparison style: 1v1"); if (packetOne.getLength() > 0) { handlePackets(mediatorMessageOne); } else { handlePackets(mediatorMessageTwo); } } // if no data is sent, then pass our own directly else { logger.info("Number of active mediators: 0. Comparison style: No Comparison"); // our datamodel to retrieve data on our own DataModel modelOwn = DataModel.getInstance(); MediatorMessageMsg newMessage = MediatorMessageMsg.newBuilder().setHeading(modelOwn.getHeading()).setSpeed(modelOwn.getSpeed()).setSender(getId()).build(); // publish(topicName, newMessage); } Thread.sleep(1); } socketReceiverOne.close(); socketReceiverTwo.close(); logger.info("stopped"); } catch (final IllegalArgumentException e) { logger.error("Illegal argument received: " + e); } catch (final Exception e) { logger.error("Unexpected error occured: " + e); } finally { if (socketReceiverOne instanceof DatagramSocket && socketReceiverTwo instanceof DatagramSocket) { if (!socketReceiverOne.isClosed() || !socketReceiverTwo.isClosed()) { socketReceiverOne.close(); socketReceiverTwo.close(); } } } }

为了节省您的时间,让我分享我对此事的看法。 我怀疑这个问题在这个部分:

socketReceiverOne.receive(packetOne); ByteArrayInputStream firstInput = new ByteArrayInputStream(buf); mediatorMessageOne = MediatorMessageMsg.parseDelimitedFrom(firstInput); socketReceiverTwo.receive(packetTwo); ByteArrayInputStream secondInput = new ByteArrayInputStream(buf); mediatorMessageTwo = MediatorMessageMsg.parseDelimitedFrom(secondInput);

对我来说,程序似乎期望一个软件包,当它不能接收它时,它会一直等待。 虽然我有超时的例外条件,但我无法完成。

private int socketTimeout = 1000 * 2;// 2sec socketReceiverOne.setSoTimeout(socketTimeout); socketReceiverTwo.setSoTimeout(socketTimeout);

有什么想法吗?

I've a class which is responsible for listening two other machines which have exactly the same classes, so it's a network of three computers having the same code. The connection is there and I can see them passing data to each other. Everything until there works OK.

Things get tricky when I take out one of the machines and observe how the other two behave. Expectedly, when one of the machines stops working for some reason, other two should continue. And if two of them stop, the remaining should go on.

I tried to implement this mechanism below. However, when I take out one of the machines, the program keeps waiting, so it does not switch to "two-way comparison mode".

public void listen() { try { logger.info("Creating listener sockets"); while (isRunning) { final byte[] buf = new byte[bufferSize]; final DatagramPacket packetOne = new DatagramPacket(buf, buf.length); final DatagramPacket packetTwo = new DatagramPacket(buf, buf.length); MediatorMessageMsg mediatorMessageOne = null; MediatorMessageMsg mediatorMessageTwo = null; try { socketReceiverOne.receive(packetOne); ByteArrayInputStream firstInput = new ByteArrayInputStream(buf); mediatorMessageOne = MediatorMessageMsg.parseDelimitedFrom(firstInput); socketReceiverTwo.receive(packetTwo); ByteArrayInputStream secondInput = new ByteArrayInputStream(buf); mediatorMessageTwo = MediatorMessageMsg.parseDelimitedFrom(secondInput); logger.trace("Received packets"); } catch (final SocketTimeoutException e) { logger.trace(e.getMessage()); continue; } catch (final SocketException e) { logger.warn(e); logger.warn("Ignore the error and go on."); continue; } catch (final IOException e) { logger.error("Incoming communication stopped!"); logger.error(e); stop(); } // if two mediators sent the data, it's OK if (packetOne.getLength() > 0 && packetTwo.getLength() > 0) { handlePackets(mediatorMessageOne, mediatorMessageTwo); logger.info("Number of active mediators: 2. Comparison style: 1v1v1"); } // if only one sent the data, compare it with our own else if (packetOne.getLength() > 0 || packetTwo.getLength() > 0) { // whicehever sent the data, compare its data with our own logger.info("Number of active mediators: 1. Comparison style: 1v1"); if (packetOne.getLength() > 0) { handlePackets(mediatorMessageOne); } else { handlePackets(mediatorMessageTwo); } } // if no data is sent, then pass our own directly else { logger.info("Number of active mediators: 0. Comparison style: No Comparison"); // our datamodel to retrieve data on our own DataModel modelOwn = DataModel.getInstance(); MediatorMessageMsg newMessage = MediatorMessageMsg.newBuilder().setHeading(modelOwn.getHeading()).setSpeed(modelOwn.getSpeed()).setSender(getId()).build(); // publish(topicName, newMessage); } Thread.sleep(1); } socketReceiverOne.close(); socketReceiverTwo.close(); logger.info("stopped"); } catch (final IllegalArgumentException e) { logger.error("Illegal argument received: " + e); } catch (final Exception e) { logger.error("Unexpected error occured: " + e); } finally { if (socketReceiverOne instanceof DatagramSocket && socketReceiverTwo instanceof DatagramSocket) { if (!socketReceiverOne.isClosed() || !socketReceiverTwo.isClosed()) { socketReceiverOne.close(); socketReceiverTwo.close(); } } } }

To save your time, let me share my opinion on the matter. I suspect the problem to be in this part:

socketReceiverOne.receive(packetOne); ByteArrayInputStream firstInput = new ByteArrayInputStream(buf); mediatorMessageOne = MediatorMessageMsg.parseDelimitedFrom(firstInput); socketReceiverTwo.receive(packetTwo); ByteArrayInputStream secondInput = new ByteArrayInputStream(buf); mediatorMessageTwo = MediatorMessageMsg.parseDelimitedFrom(secondInput);

To me it seems like the program expects a package and when it cannot receive it, it keeps waiting. Although I have time out exception condition, I cannot get this done.

private int socketTimeout = 1000 * 2;// 2sec socketReceiverOne.setSoTimeout(socketTimeout); socketReceiverTwo.setSoTimeout(socketTimeout);

Any thoughts?

最满意答案

好吧,我发现我错了。 我需要更多的端口(用于进出)。 一旦我合并了这些端口,问题就不再发生了。

Okay I found where I was mistaken. I needed more ports (for in and out). Once I incorporated those ports, the problem did not occur again.

更多推荐