【问题标题】:Socket programming: notify all clients before shutting server down套接字编程:在关闭服务器之前通知所有客户端
【发布时间】:2013-07-14 00:52:35
【问题描述】:

我正在尝试使用this 教程实现一个服务器(能够接受多个客户端)和一个客户端并进行一些扩展。 除了一个功能外,一切都很好: 当服务器运行 1 分钟后,它会关闭,每个客户端必须打印消息“服务器正在关闭”并关闭。

在我对 KKMultiServer 的模拟中,我在 main 方法中以这种方式实现它:

long in1minute = 10*1000;
        Timer timer = new Timer();
        timer.schedule( new TimerTask(){
              public void run() {
                  for(int i=0;i<startedThreads.size();i++){
                      try {
                        startedThreads.get(i).Close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                  }

                  listening=false;
               }
         },  in1minute );

每个启动的线程都被添加到向量中。

在我对KKMultiServerThread 的模拟中,此代码应将消息发送给客户端(我对KKProtocol 的模拟正确地进行)

public void Close() throws IOException{
    String outputLine=p.processInput("shut");
    out.println(outputLine);
    out.close();
    in.close();
    socket.close();
}

服务器正常停止,但客户端不打印消息“服务器正在关闭”。然后,如果我在服务器关闭时调用客户端,我会得到:

     [java] Exception in thread "main" java.net.SocketException: Connection rese
tClient: d
     [java]     at java.net.SocketInputStream.read(SocketInputStream.java:189)
     [java]     at java.net.SocketInputStream.read(SocketInputStream.java:121)
     [java]     at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
     [java]     at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
     [java]     at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
     [java]     at java.io.InputStreamReader.read(InputStreamReader.java:184)
     [java]     at java.io.BufferedReader.fill(BufferedReader.java:154)
     [java]     at java.io.BufferedReader.readLine(BufferedReader.java:317)
     [java]     at java.io.BufferedReader.readLine(BufferedReader.java:382)
     [java]     at ist.assignment2.Client.main(Client.java:31)
     [java]

Client.java:31 的代码

 while ((fromServer = in.readLine()) != null) {

...然后模拟为KKClient

那么为什么客户端不打印消息并退出呢?

【问题讨论】:

  • 还有什么可以关闭套接字的吗?注意你不需要in.close()socket.close() 应该在 finally 块中。这个协议的目的是什么? 每个客户端设置 1 分钟的读取超时不是更好,如果它触发 然后 发送关闭消息并关闭 那个客户端?我>
  • @EJP 不,我发布了所有相关内容。该协议根据客户端输入生成正确的服务器输出。好吧,它是关于实施我现在的想法,而不是实施一些最佳概念。我只是想了解为什么它不起作用。我对 while ((fromServer = in.readLine()) != null) 循环有点困惑。它实际上是如何在需要的时间开始读取每个输入的以及何时退出?
  • readLine() 阻塞,直到收到完整的行或 EOS。
  • @EJP 为什么没有线路时循环不退出(如果客户端没有发送任何内容)?直到那时循环才冻结吗?怎么来的?

标签: java sockets client-server


【解决方案1】:

如果对方尚未确认所有数据,则不应关闭 TCP 套接字。这种机制被设计到大多数应用程序协议中。例如对于 HTTP、SMTP、IMAP、POP3,当连接应该关闭时,服务器会发出信号,客户端会关闭套接字,然后服务器会关闭套接字。

在您的情况下,您可以按如下方式扩展您的 Close 方法:

public void Close() throws IOException {
    String outputLine = p.processInput("shut");
    out.println(outputLine);
    // signal the client that the connection should be closed
    socket.shutdownOutput();
    // wait on ack by blocking until EOF is received
    if (in.read() != -1) {
       throw new RuntimeException("unexpected data sent by client");
    }
    // close socket
    socket.close();
}

【讨论】:

  • 嗯,现在发生了一些完全奇怪的事情。当计时器经过 1 分钟时,没有任何反应,客户端和服务器仍在工作。然后服务器将处理第 1 个命令,如果我发送第 2 个命令客户端成功停止(但没有消息“服务器正在关闭”),服务器会抛出您编写的运行时异常并继续运行 oO
  • @IAM 您能否发布一个完整且最小的示例来说明问题。我想还有其他问题会导致这个问题,例如线程同步错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-06
  • 2013-09-29
  • 1970-01-01
相关资源
最近更新 更多