【问题标题】:Further problems with ObjectInputStreams with Sockets带有套接字的 ObjectInputStreams 的更多问题
【发布时间】:2014-03-01 12:41:25
【问题描述】:

在另一个线程中,我寻求有关套接字和 ObjectInputStreams 问题的帮助。

swapnil7 回答并给了我帮助: 我的代码说:

        while(!line.equalsIgnoreCase("exit")){
            while(in.available() <= 0){}
                line = in.readObject().toString();
                System.out.println(">>> recieved: " + line);
        }

我想,in.available() 请求准备接收多少字节。所以我做了一个循环,什么也没做,直到 in.available() 说有更多的字节要接收。然后swapnil7说,我必须这样做:

        while(!line.equalsIgnoreCase("exit")){
            while(in.available() <= 0){
                line = in.readObject().toString();
                System.out.println(">>> recieved: " + line);
            }
        }

我工作过。但这只是测试应用程序。我的真实应用程序,不仅将 ObjectStreams 用于文本,看起来像这样:

    while(true){
        try{
            while(in.available() <= 0) {
                Object obj = in.readObject();
                if(obj instanceof ArrayList){
                    Main.info("recieved package: " + obj.getClass());
                    app.sendClientUpdate(this, obj);
                }else{
                    Main.info("recieved unexpected package: " + obj.toString());
                }
            }

        }catch(Exception ex){
            Main.error("Error while reading: " + ex.getMessage());
        }
    }

这应该是一模一样的东西,但是会抛出异常:

读取时出错:类型代码无效:42

在代码中抛出:

Main.error("读取时出错:" + ex.getMessage());

当我想到时,这就是我所期望的,in.available() 返回可接收字节的数量。我想,这个异常意味着 inputStream 阻塞了读取,因为缓冲区是空的。 现在,我很困惑,因为一方面,我不得不像 swapnil7 所说的那样去做,另一方面,我的大应用程序抛出了异常。 谁能向我解释这两种不同的行为?

附:英语仍然不是我的母语 :) 所以对于错误我很抱歉。

编辑: 所以,这里是写作部分。它每秒向套接字写入超过一次(我认为是 6 次左右):

public void sendPackets() throws IOException{
    out.writeObject(tanks);
    out.flush();
    out.writeObject(enemies);
    out.flush();
    out.writeObject(bullets);
    out.flush();
}

此代码完美运行,不抛出任何异常,也不会中止(一切都经过测试)。写入的对象是可序列化对象的ArrayLists,包含一些原始数据。

【问题讨论】:

  • 不要使用 available()。从流中读取,直到你读完你想读的所有东西,这个流将阻塞,直到你想读的东西被接收到。不要捕捉异常。并且不要吞下异常堆栈跟踪。打印异常的堆栈跟踪,以了解它们的类型和来源。
  • 您的流看起来已损坏,因此您可能也应该发布编写代码。
  • @JB Nizet 我一直在写 Stream,但是当我忽略 in.available() 时,什么也没有发生。 streamReader 什么都不做
  • 您似乎在同一个连接中混合了文本和二进制文件......这很容易中断。如果我是你,我会选择一种或另一种方式,但不会两者兼而有之。而且由于您似乎主要使用二进制文件,因此一直使用二进制文件 - 或者使用 Base64 对二进制内容进行编码。
  • 我以为String类是可序列化的??我将字符串实例作为变量发送,我认为这应该是可能的?

标签: java sockets networking stream


【解决方案1】:

不要使用in.available()

只需致电in.readObject()

如果还没有要读取的内容,readObject() 调用将阻塞,直到一些数据从套接字的另一端到达。如果套接字关闭,那么您的代码将获得某种 IOException 而不是返回一个对象。

如果您想解释为什么在您摆脱 available() 调用后代码会失败,您需要确切地向我们展示您在做什么。理想情况下,为客户端和服务器端创建一个SSCCE,>>我们

不管怎样,“无效类型代码:42”表示流损坏,或者写入和读取操作序列之间存在不匹配。有很多可能的解释,但没有SSCCE,就不可能进一步缩小范围。

【讨论】:

    【解决方案2】:

    好的-.- 就这么简单:我忘记在客户端和服务器上使用相同的生成序列化 ID。通过为每个对象使用相同的序列化 ID,一切都运行良好。 但无论如何,谢谢你的帮助!

    【讨论】:

    • 这不会导致您在此处描述的异常。
    • 好吧,引发了异常,因为应用程序无法使用错误的序列化 ID 反序列化对象。所以数据流似乎已损坏且无法读取
    猜你喜欢
    • 1970-01-01
    • 2020-02-04
    • 1970-01-01
    • 2020-09-30
    • 2016-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多