简体   繁体   中英

ObjectOutputStream over a TCP Socket

I wrote a peer-to-peer networked game in Java using the java.net package and for some reason the Socket between the client and the server closes or gets corrupted. I am calling this "peer-to-peer" because one of the clients also runs a server class, which is just a custom class I wrote that accepts Socket connections - one from the other computer and one from the client computer. The connection is being used to move objects back and forth using ObjectOutputStream and ObjectInputStream.

The Socket error happens irregularly. The connection is usually open for 5-10 minutes before there is a problem. Sometimes it closes when a new game is started, other times it closes while a game is in progress.

  1. Should I be using keepAlive to keep the connection open?
  2. Does anyone have a suggestion on how I should go about troubleshooting this problem?

Here is the code generating the error:

/**
 * Continually checks for messages to be read in. Then it
 * sends the messages to processMessage if a message is available.
 */
   public void listenForMessages() {
      int availableBytes;
      Object obj = null;
      try {
         availableBytes = socketStream.available();
         if (availableBytes >5) {
            obj = in.readObject();
            message = (ClientMessage) (obj);
            processMessage();
         }
      }
      catch(java.io.StreamCorruptedException utoh) {
          System.out.println("Read failed: " + utoh);
          try {
              System.out.println("Number of Bytes available: " + socketStream.available());
              utoh.printStackTrace();
              System.out.println("Attempting to close socked.");
              socketStream.close();
          }
          catch(IOException ioe) { 
              System.out.println("Unable to close: " + ioe.toString());
          }              
      }
      catch(IOException e) {
         System.out.println("Read failed" + e);
      }

Here is the error message and stack trace:

Read failed: java.io.StreamCorruptedException: invalid type code: 00
Number of Bytes available: 100

There are two sockets (two streams) active, one for each client. When the other socket throws the same error, I am seeing invalid type code: FF

Stack Trace

java.io.StreamCorruptedException: invalid type code: 00
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1355)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
at thornworks.quiz.PlayerInterface.listenForMessages(PlayerInterface.java:227)
at thornworks.quiz.PlayerInterface.actionPerformed(PlayerInterface.java:214)
at javax.swing.Timer.fireActionPerformed(Timer.java:291)
at javax.swing.Timer$DoPostEvent.run(Timer.java:221)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:641)
at java.awt.EventQueue.access$000(EventQueue.java:84)
at java.awt.EventQueue$1.run(EventQueue.java:602)
at java.awt.EventQueue$1.run(EventQueue.java:600)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:611)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

When creating networking applications it is very important to introduce network I/O logging early in the development. It will help you troubleshoot simple bugs like connection breaks and incorrect data being sent or received.

I assume that you have connection problems in your test environment: that is on local network? Can you describe your client? Is it a mobile device?

If your application needs connection to be constantly open I would recommend implementing some reconnect logic. That is if connection is broken (you detect it when performing I/O operation) you try to re-establish it with the peer.

UPDATE:

if (availableBytes >5) {
    obj = in.readObject();
    message = (ClientMessage) (obj);
    processMessage();
}

What will happen if there are several objects serialized in the available bytes? What does in.readObject() ? Does it read required amount of bytes for object serialization or everything that is available?

IMO the possible reason of the behavior you see is that the code does not expect several objects can be received at once and stored in the receive buffer. Also receive buffer can contain parts of the objects (eg object1 + two bytes of the object2).

TCP is a stream protocol and therefore you cannot determine message end easily. You should implement protocol that will determine the start and end of the message being transmitted. In the code from you

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM