5

我正在开发一个用 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 没有很多资源。当我进一步研究它时,我会不断更新这个问题。

4

5 回答 5

9

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

于 2012-03-01T13:55:10.890 回答
3

For my case, it's a silly problem but wasting me 4 hours. Just have to use outStream.writeln(""); or outStream.write(mess + "\n"); Since reader.readLine() reads until it finds '\n' character. So write() alone won't work.

于 2017-06-17T16:54:14.880 回答
0

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

于 2011-01-28T19:44:35.600 回答
0

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

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

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

如果不设置 SO Linger 会发生什么?

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

于 2011-01-28T15:59:07.693 回答
0

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

于 2011-01-29T00:32:29.570 回答