【问题标题】:ObjectOutputStream.writeObject() (on top of socket.getOutputStream()) throws broken pipe (IO Exception) when writing a serializable object写入可序列化对象时,ObjectOutputStream.writeObject()(在 socket.getOutputStream() 之上)抛出损坏的管道(IO 异常)
【发布时间】:2012-10-29 04:03:02
【问题描述】:

更新: 完整代码示例: 服务器:

ServerSocket serverSocket = new ServerSocket(8888);
Socket client = serverSocket.accept();
writer_ = new ObjectOutputStream(client.getOutputStream());
writer_.writeObject("This should be a solstice message normally.");
writer_.flush();

客户:

Socket clientSocket = new Socket(InetAddress.getLocalHost(), 8888);
ObjectInputStream reader = new ObjectInputStream(clientSocket.getInputStream());
Object obj = reader.readObject();
if (obj instanceof SolsticeMessage)
{
    SolsticeMessage message = (SolsticeMessage) obj;
    processMessage(message);
}
else
    System.out.println("Received a message of unknown type: " + obj.getClass());

当我运行代码时,客户端连接到服务器,但是它从不打印“else”分支中的 System.out.println()。此外,如果我将服务器更改如下:

ServerSocket serverSocket = new ServerSocket(8888);
Socket client = serverSocket.accept();
writer_ = new ObjectOutputStream(client.getOutputStream());
writer_.writeObject(message); // of type SolsticeMessage
writer_.flush();

写一个正确的消息,然后服务器立即抛出损坏的管道异常。

原来的问题: 我正在尝试编写一个等待客户端连接的简单服务器,如下所示:

ServerSocket serverSocket = new ServerSocket(8888);
Socket client = serverSocket.accept();
writer_ = new ObjectOutputStream(client.getOutputStream());

然后,确保 writer_ 不为空,我尝试将以下两条消息写入客户端:

writer_.writeObject("This is a string.");
writer_.writeObject(message); // where message implements Serializable
writer_.flush();

这是客户端代码:

Socket clientSocket = new Socket(InetAddress.getLocalHost(), 8888);
ObjectInputStream reader = new ObjectInputStream(clientSocket.getInputStream());
Object obj = null;
while ((obj = reader.readObject()) != null)
{
    SolsticeMessage message = (SolsticeMessage) obj;
    processMessage(message);
}

与我的预期相反(应该写入两个对象),第一个对象(字符串)发送成功,但是第二个对象(消息)抛出以下异常:

java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
at java.io.ObjectOutputStream$BlockDataOutputStream.drain(ObjectOutputStream.java:1847)
at java.io.ObjectOutputStream$BlockDataOutputStream.setBlockDataMode(ObjectOutputStream.java:1756)
at java.io.ObjectOutputStream.writeNonProxyDesc(ObjectOutputStream.java:1257)
at java.io.ObjectOutputStream.writeClassDesc(ObjectOutputStream.java:1211)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1395)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
at java.io.ObjectOutputStream.writeFatalException(ObjectOutputStream.java:1547)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:333)
at com.kivancmuslu.www.solstice.server.SolsticeServer.sendMessage(SolsticeServer.java:146)
at com.kivancmuslu.www.solstice.server.listeners.ResourceChangeListener.processResourceChange(ResourceChangeListener.java:94)
at com.kivancmuslu.www.solstice.server.listeners.ResourceChangeListener.processResourceDelta(ResourceChangeListener.java:65)
at com.kivancmuslu.www.solstice.server.listeners.ResourceChangeListener.processResourceDelta(ResourceChangeListener.java:86)
at com.kivancmuslu.www.solstice.server.listeners.ResourceChangeListener.processResourceDelta(ResourceChangeListener.java:86)
at com.kivancmuslu.www.solstice.server.listeners.ResourceChangeListener.processResourceDelta(ResourceChangeListener.java:86)
at com.kivancmuslu.www.solstice.server.listeners.ResourceChangeListener.resourceChanged(ResourceChangeListener.java:31)
at org.eclipse.core.internal.events.NotificationManager$1.run(NotificationManager.java:291)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
at org.eclipse.core.internal.events.NotificationManager.notify(NotificationManager.java:285)
at org.eclipse.core.internal.events.NotificationManager.broadcastChanges(NotificationManager.java:149)
at org.eclipse.core.internal.resources.Workspace.broadcastPostChange(Workspace.java:395)
at org.eclipse.core.internal.resources.Workspace.endOperation(Workspace.java:1530)
at org.eclipse.core.internal.events.AutoBuildJob.doBuild(AutoBuildJob.java:156)
at org.eclipse.core.internal.events.AutoBuildJob.run(AutoBuildJob.java:241)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:53)

任何想法为什么字符串对象被写入并通过网络发送而没有问题,但是我的其他序列化对象导致此异常?我还在下面附上了我的序列化类,以防万一:

package com.kivancmuslu.www.solstice.logic;

public class ResourceChangedMessage extends SolsticeMessage
{
    /**
     * 
     */
    private static final long serialVersionUID = -2877650023886033398L;

    public static enum ResourceChangeType
    {
        ADDED, REMOVED
    }

    private final String projectName_;
    private final String relativeResourcePath_;
    private final ResourceChangeType resourceChangeType_;

    public ResourceChangedMessage(String projectName, String relativeResourcePath,
                                  ResourceChangeType resourceChangeType)
    {
        projectName_ = projectName;
        relativeResourcePath_ = relativeResourcePath;
        resourceChangeType_ = resourceChangeType;
    }

    public String getProjectName()
    {
        return projectName_;
    }

    public String getRelativeResourcePath()
    {
        return relativeResourcePath_;
    }

    public ResourceChangeType getResourceChangeType()
    {
        return resourceChangeType_;
    }
}

其中 SolsticeMessage 定义为:

package com.kivancmuslu.www.solstice.logic;

import java.io.Serializable;

public abstract class SolsticeMessage implements Serializable
{
    private static final long serialVersionUID = 4048501241385740686L;

    public abstract String toString();
}

谢谢你,

【问题讨论】:

    标签: java io serversocket objectoutputstream


    【解决方案1】:

    我强烈怀疑连接的另一端正在关闭它。例如,如果它是另一个具有以下代码的 Java 程序:

    Socket client = serverSocket.accept();
    reader_ = new ObjectInputStream(client.getInputStream());
    reader_.readObject();
    reader_.close();
    

    ...那么您的发送代码将无处可发送第二个对象。不幸的是,你没有给我们正在监听的代码。以上是我最好的猜测。

    编辑:现在您已经发布了服务器代码,我们可以看到真正的问题。这是它试图阅读的内容:

    while ((obj = reader.readObject()) != null)
    {
        SolsticeMessage message = (SolsticeMessage) obj;
        processMessage(message);
    }
    

    ...但您首先要发送String。所以它试图将String 转换为SolsticeMessage,这将引发异常 - 并且可能 会导致整个过程停止,或者至少以关闭的连接结束。

    【讨论】:

    • 我已经用客户端代码更新了示例。因为,我确定不是这种情况,所以我忘了首先添加。对不起。
    • @KivancMuslu:查看我的编辑。您应该在侦听端看到异常...如果那仍然不是您的真实代码,请提供一个简短但完整的程序来演示问题。
    • 为一个简短而完整的程序添加了完整的服务器和客户端代码。顺便说一句,我在 Eclipse 插件设置中执行此操作,其中服务器插件在后台生成无头 Eclipse,并在此无头 Eclipse 上运行客户端插件,然后客户端连接到服务器。据我所知,这不应该影响套接字的工作方式,但是想提一下以防万一。
    • @KivancMuslu:不,这绝对是不是完整的服务器和客户端代码。您甚至没有将代码放在方法中,更不用说类了。理想情况下,创建两个控制台应用程序,只需最低限度地重现问题 - 我们可以复制、粘贴、编译、运行并查看发生了什么。
    • @KivancMuslu: 要求一个简短但完整的例子的重点绝不是你发布你的整个 实际 代码 - 而是你把它剪下来直到你可以演示 只是的问题。通常,减少它的过程会为你找到问题,你甚至不需要问一个问题。如果您创建了一个简短但完整的示例后仍然感到困惑,那么其他人可以更轻松地帮助您。我希望,如果您在聆听方面遇到异常,那么就原因而言,这应该是相当清楚的。
    猜你喜欢
    • 2018-04-20
    • 2019-01-22
    • 1970-01-01
    • 2013-07-04
    • 1970-01-01
    • 1970-01-01
    • 2011-02-12
    • 2011-05-20
    相关资源
    最近更新 更多