簡體   English   中英

編寫可序列化的對象時,ObjectOutputStream.writeObject()(在socket.getOutputStream()頂部)拋出斷線(IO異常)

[英]ObjectOutputStream.writeObject() (on top of socket.getOutputStream()) throws broken pipe (IO Exception) when writing a serializable object

更新:完整的代碼示例:服務器:

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程序:

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 所以,它試圖投出StringSolsticeMessage ,這將拋出一個異常-想必要么使整個流程下來,或至少結束了一個關閉的連接。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM