views:

124

answers:

1

I am using java sockets for communication. On the client side I have some processing and at this point I send an object to the cient. The code is as follows:

while (true) {
  try {
    Socket server = new Socket("localhost", 3000);
    OutputStream os = server.getOutputStream();
    InputStream is = server.getInputStream();

    CommMessage commMessage = new CommMessageImpl();
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(bos);
    oos.writeObject(commMessage);
    os.write(bos.toByteArray());
    os.flush();

    byte[] buff = new byte[512];
    int bytesRead = 0;
    ByteArrayOutputStream receivedObject = new ByteArrayOutputStream();
    while ((bytesRead = is.read(buff)) > -1) {
      receivedObject.write(buff, 0, bytesRead);
      System.out.println(receivedObject);
    }
    os.close();
    Thread.sleep(10000);
  } catch (IOException e) {
  } catch (InterruptedException e) {
  }
}

Next on the server side I have the following code to read the object and write the response (Which is just an echo message)

public void startServer() {
  Socket client = null;
  try {
    server = new ServerSocket(3000);
    logger.log(Level.INFO, "Waiting for connections.");
    client = server.accept();
    logger.log(Level.INFO, "Accepted a connection from: " + client.getInetAddress());
    os = new ObjectOutputStream(client.getOutputStream());
    is = new ObjectInputStream(client.getInputStream());

    // Read contents of the stream and store it into a byte array.
    byte[] buff = new byte[512];
    int bytesRead = 0;
    ByteArrayOutputStream receivedObject = new ByteArrayOutputStream();
    while ((bytesRead = is.read(buff)) > -1) {
      receivedObject.write(buff, 0, bytesRead);
    }

    // Check if received stream is CommMessage or not contents.
    CommMessage commMessage = getCommMessage(receivedObject);
    if (commMessage != null) {
      commMessage.setSessionState(this.sessionManager.getState().getState());
      ByteArrayOutputStream bos = new ByteArrayOutputStream();
      ObjectOutputStream oos = new ObjectOutputStream(bos);
      oos.writeObject(commMessage);
      os.write(bos.toByteArray());
      System.out.println(commMessage.getCommMessageType());
    } else {
      processData(receivedObject, this.sessionManager);
    }
    os.flush();
    } catch (IOException e) {
    } finally {
      try {
        is.close();
        os.close();
        client.close();
        server.close();
      } catch (IOException e) {
    }
  }
}

The above code works ok if I do not try to read data on the client side (If i exclude the code related to reading). But if I have that code, for some reason, I get some kind of deadlock when accessing input streams. Any ideas what I might have done wrong? Thanks in advance.

+3  A: 

Both client and server are attempting to read the whole input stream (i.e. everything up to EOF) but neither is sending an EOF (by calling shutdownOutput() on the socket.)

Why do you need to store the object data temporarily in a ByteArrayOutputStream? This would probably be easier to fix if you read directly from the socket input stream.

finnw
Thanks, I'll try the solution later today... But the reason why I use ByteArrayOutputStream is because I don't know what will come from the client - the stream can contain one of two types of objects. So what I do is that I fully read the stream and try to convert to one object - if that fails it can only be the other object (or an error :)). Do you think I should do it some other way?
markovuksanovic
Just read it into an Object and use instanceof. I can't see how what you're doing adds anything to that, you still have to do that anyway.
EJP
You're right. I should do some refactoring obviously. Thanks for pointing that out.
markovuksanovic