TCP套接字上的ObjectOutputStream

时间:2012-03-08 15:50:27

标签: java tcp

我使用java.net包在Java中编写了一个点对点的网络游戏,由于某种原因,客户端和服务器之间的Socket关闭或被破坏。我称之为“点对点”,因为其中一个客户端也运行一个服务器类,这只是我编写的一个接受Socket连接的自定义类 - 一个来自另一台计算机,另一个来自客户端计算机。 该连接用于使用ObjectOutputStream和ObjectInputStream来回移动对象。

Socket错误不规则地发生。在出现问题之前,连接通常会打开5-10分钟。有时它在新游戏开始时关闭,有时在游戏进行时关闭。

  1. 我应该使用keepAlive来保持连接打开吗?
  2. 是否有人建议如何解决此问题?
  3. 以下是生成错误的代码:

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

    这是错误消息和堆栈跟踪:

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

    有两个套接字(两个流)处于活动状态,每个客户端一个。当另一个套接字抛出相同的错误时,我看到无效的类型代码:FF

    堆栈跟踪

    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)
    

1 个答案:

答案 0 :(得分:1)

在创建网络应用程序时,在开发早期引入网络I / O日志记录非常重要。它可以帮助您解决简单的错误,如连接中断和发送或接收的错误数据。

我假设您的测试环境中存在连接问题:那是在本地网络上? 你能描述一下你的客户吗?它是移动设备吗?

如果您的应用程序需要连接打开,我建议实现一些重新连接逻辑。也就是说,如果连接断开(在执行I / O操作时检测到它),则尝试与对等方重新建立连接。

更新:

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

如果在可用字节中序列化了多个对象,会发生什么? in.readObject()是什么?它是否读取了对象序列化所需的字节数或所有可用的字节数?

IMO您看到的行为的可能原因是代码不希望一次接收多个对象并存储在接收缓冲区中。接收缓冲区也可以包含部分对象(例如object1 + object2的两个字节)。

TCP是一种流协议,因此您无法轻松确定消息结束。您应该实现协议,以确定正在传输的消息的开始和结束。 在你的代码中