套接字编程:在关闭服务器之前通知所有客户端

时间:2013-07-16 01:05:28

标签: java sockets client-server

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

在我的模拟中KKMultiServer我用这种方式实现它,在主方法中:

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

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

1 个答案:

答案 0 :(得分:2)

如果另一方未确认所有数据,则不应关闭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();
}
相关问题