我正在开发一个用Java编写的网络应用程序,在套接字上使用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
}
}
有时消息会通过ok,但有时我会得到标记的异常而不是对象。是不是应该强制将消息强制传递给另一方?我以某种方式错误地使用该功能?或者这是底层Java / OS网络代码中的某种错误?
谢谢!
更新:
我已经对此做了更多的窥探,似乎只有当系统的资源被某些东西征税时才会发生。我无法在VirtualBox之外复制它,但这可能只是因为VirtualBox没有很多资源可以开始。我会进一步研究这个问题。
答案 0 :(得分:7)
事实证明这个问题是由Nagle算法引起的;输出缓冲区在OS中,因此它不受flush的影响。解决方案是使用Socket.setTcpNoDelay(true)关闭Nagle的算法,并使用BufferedOutputStream在用户级别缓冲消息。
答案 1 :(得分:1)
就我而言,这是一个愚蠢的问题,但浪费了我4个小时。 只需使用 outStream.writeln(“”); 或 outStream.write(mess +“\ n”); 由于 reader.readLine()会一直读到'\ n'字符。所以单独使用write()是行不通的。
答案 2 :(得分:0)
您应该能够为每个连接发送一个对象。
为确保以有序的方式清理资源,最好关闭套接字以及输出流。
close()将调用flush,因此它应该是多余的。
如果您没有设置SO灵儿,会发生什么?
你得到的实际例外是什么?
答案 3 :(得分:0)
听起来像是从客户端到服务器的路径中的一个路由器中的防火墙由于某种原因发送RST。我不相信你的代码有什么问题。我试图复制这个问题,但不能。
答案 4 :(得分:0)
通过写入已在另一端关闭的连接可能导致连接重置。检测可以在下一个I / O或随后的I / O发生,例如,阅读。换句话说,它可能是由您的应用程序协议中的错误引起的。 SO_LINGER不会帮忙,不要惹这个。