【问题标题】:Java ObjectOutputStream on Socket not flush()ingSocket 上的 Java ObjectOutputStream 不刷新()
【发布时间】:2011-06-17 07:36:29
【问题描述】:

我正在开发一个用 Java 编写的网络应用程序,使用 Sockets 之上的 ObjectOutputStream 和 ObjectInputStream 来交换消息。我的代码如下所示:

发件人:

ObjectOutputStream out;
ObjectInputStream in;
try{
     Socket socket=new Socket(address, port);
     socket.setSoLinger(true, socketLingerTime);
     out=new ObjectOutputStream(socket.getOutputStream());
     out.writeObject(message);
     out.flush();
     out.close();
}catch (variousExceptions)...

接收者:

Object incoming;
try{
    incoming=myObjectInputStream.readObject();
}catch (SocketException socketError)
{
    if (socketError.getMessage().equals("Connection reset"))
    {
        //this is the exception I get
    }
}

有时消息正常,但有时我得到标记的异常而不是对象。冲洗不应该强制消息传递到另一边吗?我是否以某种方式错误地使用了该功能?或者这是底层 Java/OS 网络代码中的某种错误?

谢谢!

更新:

我对此做了更多的窥探,它似乎只在系统资源被某些东西征税时才会发生。我无法在 VirtualBox 之外复制它,但这可能只是因为 VirtualBox 没有很多资源。当我进一步研究这个问题时,我会不断更新这个问题。

【问题讨论】:

  • 我无法复制问题。更多细节?
  • 您能显示更多您的接收方代码吗?您是否尝试通过同一个套接字发送/接收多个消息(在这种情况下您不应该关闭流)。
  • 在接收端重置连接时,发送端是否会抛出异常?
  • 操作系统是 Red Hat Linux,在 Windows XP 之上的 VirtualBox 中运行。我确实通过同一个套接字发送和接收多条消息;这只发生在发送者关闭()它的流时,所以我去掉了其他消息代码。当它发生时,发送方没有例外。
  • 哦,是的,我正在使用 jdk1.6.0_23。

标签: java sockets flush objectoutputstream


【解决方案1】:

您应该能够在每个连接中发送一个对象。

为确保资源被有序清理,最好关闭套接字以及输出流。

close() 会调用flush,所以它应该是多余的。

如果不设置 SO Linger 会怎样?

你得到的实际异常是什么?

【讨论】:

  • 你应该可以发送多个对象。
  • @Highland,如果您在发送第一个对象后不关闭()输出。 ;)
  • 我实际上添加了 SO Linger 作为解决此问题的可能方法。没有它,问题仍然存在。实际异常是 SocketException,消息“连接重置”。
  • 此异常确实意味着另一端关闭了连接,但是您拥有的代码不应该这样做并且不会为我重现问题。我会绝对确保您正在测试的代码是您认为的那样。 close() 为您调用 flush() ,所以这无关紧要。
【解决方案2】:

听起来,从客户端到服务器的路径中的一个路由器中的防火墙出于某种原因正在发送 RST。我不相信你的代码有什么问题。我试图复制这个问题,但不能。

【讨论】:

    【解决方案3】:

    连接重置可能是由于写入另一端已关闭的连接。检测可以发生在下一个 I/O 或后续 I/O,例如一读。换句话说,它可能是由您的应用程序协议中的错误引起的。 SO_LINGER 无济于事,别惹这个。

    【讨论】:

      【解决方案4】:

      原来问题是由 Nagle 算法引起的;输出缓冲区位于操作系统内,因此不受刷新的影响。解决方案是使用 Socket.setTcpNoDelay(true) 关闭 Nagle 的算法,并使用 BufferedOutputStream 在用户级别缓冲消息。

      【讨论】:

        【解决方案5】:

        就我而言,这是一个愚蠢的问题,但浪费了我 4 个小时。 只需使用 outStream.writeln("");outStream.write(mess + "\n"); 由于 reader.readLine() 会一直读取直到找到 '\n' 字符。所以只用 write() 是行不通的。

        【讨论】:

          猜你喜欢
          • 2013-04-18
          • 2011-01-13
          • 2012-01-12
          • 2011-04-27
          • 2012-08-08
          • 1970-01-01
          • 2015-01-05
          • 2013-05-09
          • 2018-08-26
          相关资源
          最近更新 更多