【问题标题】:outputStream shutdown causes the other Streams blocks?outputStream 关​​闭会导致其他 Streams 阻塞?
【发布时间】:2023-03-03 21:22:01
【问题描述】:

我有一个有很多客户端的服务器。每个连接都到达服务器

如果被接受,我会将其发送到一个线程:

server= serverSocketcht.accept();
new ThrdConv(server).start(); 

在 ThrdConv 线程中,我将输入流和输出流设置为这个新的连接

    this.OOS=new ObjectOutputStream(server.getOutputStream());
    this.OIS=new ObjectInputStream(server.getInputStream());

然后我将到达的连接(我们称之为新客户端)存储在客户端列表中:

  if(isLogged){ // if success login!
      thsisUser= new Clientuser(server,OOS,OIS,Omsg.my_gender,Omsg.userID);
        boolean IsAdded= EIQserver.OnlineusersList.add(this.thsisUser);

一切正常,客户端可以发送消息并与其他客户端聊天...

问题是当客户离开时,我得到了这个异常:

SEVERE: null
java.io.EOFException
at    
java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2571)

这是我的离开函数:

 Iterator<Clientuser> iterator = EIQserver.OnlineusersList.iterator();
   if(EIQserver.OnlineusersList.size()>=1)
 Omsg.type= MessageType.Leave;


   sendMessage(OLeavemsg); // tell the partner that I am leaving...

       while (iterator.hasNext()) {
         Clientuser next = iterator.next();
         if (next.ID.equals(OLeavemsg.userID)) 
         {
            next.ClientPort.shutdownInput(); // ClientPort is a socket of this Client
            next.ClientPort.shutdownOutput();
           iterator.remove();// remove the partner
         }
         break;
     }     
       // end leave////////////////////////////////////////////////

连接已从列表中删除,但上述异常停止了服务器...

帮我解决这个复杂的问题

【问题讨论】:

    标签: java objectoutputstream


    【解决方案1】:

    您应该关闭 this.OOS 和 this.OIS。他们将递归地关闭内部流。在您当前的情况下,外部流失败,因为客户端首先关闭。您可以查看 Object*Stream,它们的 close 方法也可以关闭内部流。

    【讨论】:

    • 您不需要同时关闭 OOS 和 OIS。关闭任何一个都会关闭另一个流和套接字。建议关闭 OOS,但使用 shutdownInout() 解除对挂起读取的阻塞是完全合法的,如果您正确处理产生的异常。他不是。这是这里唯一的问题。
    【解决方案2】:

    谢谢 Mikhail,您的回答是解决方案的关键。 对于其他读者,我将描述我是如何解决这个问题的:

    • 首先我按照您的建议关闭了 OOS、OIS...。
    • 其次我停止线程.. 如何停止线程? :
      • 我声明了名为“Running”的新布尔变量,并将线程主循环的条件设置为 while(running) 当我想停止线程的主循环时,我设置了 running=false 这停止使用封闭的流!

    【讨论】:

    • 欢迎,使用中断是停止线程的更好方法stackoverflow.com/a/10962613/2031799
    • @Mikhail 不是在 java.net 类中存在阻塞的挂起读取时,它不是。行为未定义。
    【解决方案3】:

    您关闭输入,读取输入时收到 EOFException。这正是应该发生的事情。在读取 ObjectInputStream 时,无论如何您都必须捕获 EOFException。这里根本不存在“复杂问题”。只是糟糕的异常处理。

    【讨论】:

    • 这实际上是关闭 otter-most 流而不产生异常的经验法则。
    • 经验法则是关闭最外层的输出流。如果要避免异常,则不能在另一个线程正在读取输入流时关闭输入流,因为这也会引发异常,并且比 EOFException 更严重,无论如何都必须处理它。我个人没有异常恐惧症。
    • EJP,谢谢,我必须说你帮了我很大的忙,通知我不要忽略处理异常...
    猜你喜欢
    • 1970-01-01
    • 2014-02-05
    • 2014-04-03
    • 1970-01-01
    • 2015-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-01
    相关资源
    最近更新 更多