2012-07-18 65 views
0

我有多个客户端和一个服务器。服务器在一个线程中处理每个客户。客户必须向客户发送客户对象。我检查了thisthis,其中谈到了错误java.io.StreamCorruptedException: invalid type code: AC,这正是我所拥有的。重复写入ObjectInputStream

但我不明白提出的解决方案。他继承了ObjectOutputStream,并且简单的不会在第二次和后面的时间内写入头部对象必须被发送。这不适合我。

是否有另一种解决方案通过TCP套接字发送自定义对象?我的客户每隔10秒收集一次数据并重新创建发送的对象。

对不起,如果我重复,我正在阅读很多类似的问题,但没有找到我的方案的答案。

预先感谢

EDIT

发送方法(在客户端)

public void TCPEchoClientSend(MonitoredData _mData) throws IOException { 
     if (_mData == null) 
      throw new IllegalArgumentException("Parameter: <Monitored Data> empty.");   
     ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); 

     // Send the encoded object to the server 
     oos.writeObject(_mData); 

     oos.close(); 

     System.out.println("Client sent the monitored data package."); 

    } 

接收

public static void handleEchoClient(Socket client, Logger logger) { 
     try { 
      MonitoredData mdata; 
      // Get the input and output I/O streams from socket 
      ObjectInputStream ois = new ObjectInputStream(client 
        .getInputStream()); 
      ObjectOutputStream oos = new ObjectOutputStream(client 
        .getOutputStream()); 

      // Receive until client closes connection, indicated by -1; 
      while ((mdata = (MonitoredData) ois.readObject()) != null) { 

       System.out.println("Got received data. Ready to save."); 

       hdb.saveOrUpdate(mdata); 

       System.out.println("Monitored Data arrived at home."); 

      } 

      // logger.info("Client " + _clntSock.getRemoteSocketAddress()+ 
      // ", echoed " + totalBytesEchoed + " bytes."); 

     } catch (IOException ex) { 
      logger.log(Level.WARNING, "Exception in echo protocol", ex); 
     } catch (ClassNotFoundException e) { 
      logger.log(Level.WARNING, "Exception in echo protocol", e); 
     } finally { 
      try { 
       client.close(); 
      } catch (IOException e) { 
      } 
     } 
    } 

回答

2

在套接字的两端使用相同的ObjectOutputStreamObjectInputStream,并查找ObjectOutputStream reset()和writeUnshared()方法。

查看this answer的讨论。

+0

所以我应该在我的发送/接收方法之外实例化它们?比如在构造函数中,例如? – 2012-07-18 23:31:50

+0

那么,显然它工作:)预先感谢,我仍然不得不继续学习这些流 – 2012-07-18 23:43:44

+0

@PedroDusso做得好。实际上,为了缓冲的原因以及经济上的努力,您应始终在套接字的整个生命周期中使用相同的流/读者/作者,而不管它们是什么类型。 – EJP 2012-07-18 23:53:25

-1

的ObjectInputStream和ObjectOutputStream的是有状态。所以你需要匹配他们的生命周期。您是否在每次发送对象网页时(即每隔10秒)在每个客户端实例化新的输出流?是的,你最好在服务器上实例化一个相应的输入流。请注意,这是最安全和最干净的选项,但它通过电线发送更多数据。

另一方面,如果你要保持流畅,那么你需要担心几件事情。首先,你只发送不可变的对象吗?否则,您可能无法传达所需内容(串行化只写入一次对象,然后将引用写入先前序列化的对象)。

+0

有状态并不是你需要匹配生命周期的唯一原因:有一个流头,它是AC的源头;并且每次写入和读取使用新的流不是“最安全和最干净的选项”。 – EJP 2012-07-18 22:33:17

+0

@EJP,我不是说每个人都写。更像松散意义上的“交易”。基本上,如果您最终重写了自第一次写入以来发生更改的对象,那么您就是在寻求麻烦。 – 2012-07-19 02:20:13

+1

完全不是,只要在重新发送时或在每个“事务”之前调用reset()即可。 – EJP 2012-07-22 03:52:39