【问题标题】:Sending something to SocketInputStream before Socket.getInputStream? [duplicate]在 Socket.getInputStream 之前向 SocketInputStream 发送一些东西? [复制]
【发布时间】:2016-11-16 00:44:04
【问题描述】:

我刚才遇到了一个奇怪的错误。我在玩 Serializable 对象,我正在使用两个对象,通过 Socket 连接相互通信。这两个应用程序相同(Peer 2 peer),但有两个实例正在运行并尝试通信。

问题似乎围绕着从套接字InputStream 获取ObjectInputStream。我的错误发生在reader = new ObjectInputSream(cliIn),我被抛出了一个 SocketTimeoutException(这本身很奇怪,我希望在装饰我的流时不会在read()。下面是我尝试做的事情。

Socket clientSocket;
clientSocket = new Socket(InetAddress.getByName(aHostIP), aPort);
clientSocket.setSoTimeout(3000);

InputStream cliIn = clientSocket.getInputStream();
ObjectInputStream reader = null;
reader = new ObjectInputStream(cliIn); // <--- Error here
ObjectOutputStream writer;
writer = new ObjectOutputStream(new BufferedOutputStream(
     clientSocket.getOutputStream()
));

writer.writeObject(new Request(aPort));
writer.flush();

奇怪的是,如果我将 ObjectInputStream 的创建移动到我写到 OutputStream 之后(此时另一个对象会响应请求),那么就不会再出现错误了。

Socket clientSocket;
clientSocket = new Socket(InetAddress.getByName(aHostIP), aPort);
clientSocket.setSoTimeout(3000);   

ObjectOutputStream writer;
writer = new ObjectOutputStream(new BufferedOutputStream(
     clientSocket.getOutputStream()
));

writer.writeObject(new Request(aPort));
writer.flush();

InputStream cliIn = clientSocket.getInputStream();
ObjectInputStream reader = null;
reader = new ObjectInputStream(cliIn); // <--- No more error

另一方(响应方)如下所示:

ObjectInputStream in = new ObjectInputStream(aConnection.getInputStream());
Object req = in.readObject();
SysIO.print("FROM OBJECT! : " + req.toString());
SysIO.print("FROM OBJECT! Port: " + ((Request) req).getPort());

Request res = new Request(15);

ObjectOutputStream out = new ObjectOutputStream(
      new BufferedOutputStream(aConnection.getOutputStream()));
out.writeObject(res);
out.flush();

它现在可以工作,但我很想知道问题出在哪里,以供将来参考。我可以看到可能很难准确地说出来,但也许你有一些进一步调查的指针,并发问题,我使用 Sockets 或 Buffers 是否错误?

(我省略了一些错误处理以使其更清晰。)

【问题讨论】:

    标签: java multithreading sockets


    【解决方案1】:

    答案在ObjectInputStream documentation

    public ObjectInputStream(InputStream in)
                      throws IOException
    

    创建一个从指定 InputStream 读取的 ObjectInputStream。 从流中读取序列化流标头并进行验证。此构造函数将阻塞,直到相应的 ObjectOutputStream 写入并刷新标头

    如果安装了安全管理器,则此构造函数将在由覆盖 ObjectInputStream.readFields 或 ObjectInputStream.readUnshared 方法的子类的构造函数直接或间接调用时检查“enableSubclassImplementation”SerializablePermission。

    参数:

    in - 要读取的输入流

    投掷:

    StreamCorruptedException - 如果流标头不正确

    IOException - 如果在读取流标头时发生 I/O 错误

    SecurityException - 如果不受信任的子类非法覆盖安全敏感方法

    NullPointerException - 如果in 为空

    在构造过程中,流试图从socket中读取一个序列化头,但是socket读取超时,因为对方还没有发送任何序列化对象。

    【讨论】:

    • 非常感谢您的回答。所以这是为了得到抛出SocketTimeoutException的头部?据我了解,没有办法 100% 确定地检查缓冲区是否为空。这样的操作是必要的还是足以使我将输入和输出流的打开与上述服务器匹配? (建议here?)
    • 是的,套接字超时是由于读取流标头造成的,因为当时没有可读取的标头。在服务器发送其 ObjectOutputStream 标头之前,您的客户端无法创建 ObjectInputStream,直到您的客户端首先发送其 ObjectOutputStream 后才会发生这种情况。
    猜你喜欢
    • 2014-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-09
    • 2016-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多