0

UPDATE: Full code example: Server:

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();

Client:

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());

When I run the code, client connects to the server, however It never prints the System.out.println() in the 'else' branch. Additionally, if I change the server as below:

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

to write a proper message, then the server throws broken pipe exception immediately.

The original question: I am trying to write a simple server that waits for a client to get connected as follows:

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

Then, making sure writer_ is not null, I try to write the following two messages to the client:

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

Here is the client code:

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);
}

Contrary to my expectations (where both object should be written), the first objects (String) is sent successfully, however the second object (message) throws the following exception:

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)

Any ideas why string object is written and sent over the network without a problem, however my other serialized object causes this exception? I also attach my Serialized class below just in case it helps:

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_;
    }
}

where SolsticeMessage is defined as:

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();
}

Thank you,

Kivanc Muslu
  • 13
  • 1
  • 6

1 Answers1

1

I strongly suspect that the other end of the connection is closing it. For example, if it's another Java program which has code of:

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

... then there'd be nowhere for your sending code to send the second object. Unfortunately you haven't given us the code that's listening. The above is my best guess though.

EDIT: Now you've posted your server code, we can see the real problem. Here's what it's trying to read:

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

... but you're sending it a String first. So it's trying to cast a String to a SolsticeMessage, which will throw an exception - and presumably that is either bringing the whole process down, or at least ending up with a closed connection.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I have updated the example with the client code. Since, I was sure this wasn't the case, I forgot to add at the first place. Sorry. – Kivanc Muslu Nov 08 '12 at 21:16
  • @KivancMuslu: See my edit. You should see the exception on the listening side... If that's *still* not your real code, please give a short but *complete* program demonstrating the problem. – Jon Skeet Nov 08 '12 at 21:17
  • Added the full server and client codes for a short and complete program. By the way, I am doing this in an Eclipse plug-in setting where the server plug-in spawns a headless Eclipse in the background and runs the client plug-in on this headless Eclipse and then the client connects to the server. To my best knowledge, this should not affect the way sockets work, however wanted to mention just in case it helps. – Kivanc Muslu Nov 08 '12 at 22:37
  • 1
    @KivancMuslu: Nope, that is absolutely *not* the full server and client code. You haven't put the code even in methods, let alone classes. Ideally, create two console apps with just the bare minimum to reproduce the problem - something we can copy, paste, compile, run, and see what's happening. – Jon Skeet Nov 08 '12 at 22:43
  • Jon, your first reply (that the client was closing connection) was correct. My application was far too complex (as I mentioned I was running and Eclipse inside Eclipse) to create a simple running version, however I realized that the second Eclipse was being killed at some point, which was also closing the connection (and making future writes fail). I still have no idea why string writes do not raise the exception but only the object writes raise the exception though. In any case, thanks for the help! – Kivanc Muslu Nov 09 '12 at 06:36
  • 1
    @KivancMuslu: The point of asking for a short but complete example is never that you post your whole *actual* code - it's that you cut it down until you can demonstrate *just* the problem. Often, the process of cutting it down will find the problem for you, and you won't even need to ask a question. If you're still puzzled *after* creating a short but complete example, it makes it much easier for others to help you. I would expect that if you've got an exception at the listening side, that should be reasonably clear in terms of a cause. – Jon Skeet Nov 09 '12 at 06:43
  • Jon, there are no exceptions in the listening side because when my headless Eclipse quits, it was killing the socket without raising any more java exceptions. Again, the simple example over two plug-ins and two Eclipse would still be really complex to generate (and even build and run for other people), that is why I never tried it. – Kivanc Muslu Nov 09 '12 at 23:02
  • @KivancMuslu: But I doubt that any part of the problem was the fact that it was running as Eclipse plugins - simple console apps would probably have been fine. (I also suspect that Eclipse was still logging an exception when it died... you just need to find out where.) – Jon Skeet Nov 09 '12 at 23:31
  • No, it did not. Because the headless Eclipse was quitting normally. I just did not know the IApplication API and how it interacted with the headless Eclipse. So, the same code with the console applications would never generate the same error (I actually have not changed anything in my client-server protocol to fix the issue). – Kivanc Muslu Nov 10 '12 at 01:00