Java 优雅终止套接字线程
根据示例,简单套接字服务器客户端将在发送.bye时终止。下面的代码使用基于线程的方法来接受多个客户端,但不处理客户端终止,并将通过重复null出错 上述链接中的第一个示例导致客户端和服务器退出。下面的服务器代码没有在收到“.bye”时断开连接的规定。我希望客户端能够正常地断开与服务器的连接。当从客户端收到“.bye”时,服务器应关闭连接。我认为这需要在Java 优雅终止套接字线程,java,sockets,exception-handling,Java,Sockets,Exception Handling,根据示例,简单套接字服务器客户端将在发送.bye时终止。下面的代码使用基于线程的方法来接受多个客户端,但不处理客户端终止,并将通过重复null出错 上述链接中的第一个示例导致客户端和服务器退出。下面的服务器代码没有在收到“.bye”时断开连接的规定。我希望客户端能够正常地断开与服务器的连接。当从客户端收到“.bye”时,服务器应关闭连接。我认为这需要在System.out.println(streamIn.readUTF())中处理在ChatServerThread中 更新问题以反映答案反馈,请
System.out.println(streamIn.readUTF())中处理代码>在ChatServerThread中
更新问题以反映答案反馈,请参阅原始代码的历史记录:
import java.net.*;
import java.io.*;
public class ChatServerThread implements Runnable
//public class ChatServerThread extends Thread
{ private Socket socket = null;
private ChatServer server = null;
private int ID = -1;
private DataInputStream streamIn = null;
private DataOutputStream streamOut = null;
public ChatServerThread(ChatServer _server, Socket _socket)
{ server = _server; socket = _socket; ID = socket.getPort();
}
public void run() {
try {
handleClient();
} catch( EOFException eof ) {
System.out.println("Client closed the connection.");
} catch( IOException ioe ) {
ioe.printStackTrace();
}
}
public void handleClient() throws IOException {
boolean done = false;
try {
System.out.println("Server Thread " + ID + " running.");
while (!done) {
String nextCommand = streamIn.readUTF();
if( nextCommand.equals(".bye") ) {
done = true;
} else {
System.out.println( nextCommand );
}
}
} finally {
streamIn.close();
streamOut.close();
socket.close();
}
}
public void open() throws IOException
{
streamIn = new DataInputStream(new BufferedInputStream(socket.getInputStre
am()));
streamOut = new DataOutputStream(new BufferedOutputStream(socket.getOutput
Stream()));
}
public void close() throws IOException
{ if (socket != null) socket.close();
if (streamIn != null) streamIn.close();
if (streamOut != null) streamOut.close();
}
}
第一个错误是由于实现了可运行的。第二个我不确定,java.io.*
是导入的,所以我不确定它为什么会抱怨
ChatServer.java:34: error: cannot find symbol
client.start();
^
symbol: method start()
location: variable client of type ChatServerThread
一般来说,您不会因为客户端说再见而关闭服务器。这意味着任何用户都可以连接到您的服务器并在没有您控制的情况下远程关机。关闭服务器由服务器的管理员或所有者处理,通常通过在服务器上通过经过身份验证的ssh会话运行命令来完成。在unix/linux上,您可以运行:
service chatserver stop
这是另一个主题,如何使其工作,但只是给你一个最佳实践的一般概述。现在,如果您想在对话结束后关闭客户端。这更有意义:
public class ChatServerThread implements Runnable {
.......
public void run() {
try {
handleClient();
} catch( EOFException eof ) {
System.out.println("Client closed the connection.");
} catch( IOException ioe ) {
ioe.printStacktrace();
}
}
public void handleClient() throws IOException {
boolean done = false;
try {
while(!done) {
String nextCommand = streamIn.readUTF();
if( nextCommand.equals(".bye") ) {
done = true;
} else {
System.out.println( nextCommand );
}
}
} finally {
streamIn.close();
streamOut.close();
socket.close();
}
}
}
然后,您可以释放该线程以服务于下一个客户机,或者干脆将其关闭。使用DataInputStream,当客户端关闭套接字而不发送“.bye”时,您将得到一个EOFEException。因此,您可以在IOException之前捕获EOFEException,然后简单地关闭
注意,我并没有将Thread子类化。相反,我实现了一个Runnable,如果您将来想创建线程池或其他更高级的东西,它将为您提供更大的灵活性。您在哪里将ChatServer类中的线程实例设置为null?接受客户端连接serverSocket.accept()的代码在循环中。您只需要运行循环的固定次数,该次数等于客户端的数量。在您的情况下,您的程序将在serverSocket.accept()调用上被阻止。“若你们能处理好这个案子,其余的事情应该能解决。”我希望罗杰默最初的问题得到澄清。希望在服务器收到匹配的readUTF
语句后正常断开客户端连接。我不应该包括无关的例子。我澄清了最初的问题,我不应该包括我所引用的例子。希望在ChatServerThread
中断开客户端连接。我的答案不会改变,因为该代码是服务器为客户端提供服务的线程循环。我移动了try语句,使其包围while循环,因此如果抛出异常,它将结束对话。通常,当您从套接字流中获得异常时,您希望这样做。加上EOFEException无论如何都应该关闭流。除了关闭流和套接字的finally
部分外,它工作得很好:错误:未报告的异常IOException;必须捕获或声明为抛出streamIn.close()代码>问题代码已更新。当客户端发出“.bye”清除断开连接时。如果使用ctrl-C,服务器终端上将显示空条目。有没有办法让服务器在客户端断开连接时输出有用的内容?因此close()会引发IOException,因此您也必须处理这些异常。通常,我只是让所有IOException冒泡并从我的客户机循环方法中跳出,然后在线程的边界捕捉它们,记录它们,然后让线程死亡或返回到线程池。IOExceptions,当处理来自套接字的流时,通常意味着客户机由于网络错误、超时、终止或客户机只是关闭其套接字端而丢失。在任何情况下,这都意味着对话结束了,所以清理干净,继续前进。这是有道理的,听起来是一个理想的解决方案。我已经更新了问题,以包括在实施更改时收到的两个错误。