我正在尝试通过创建套接字并将其连接到服务器,发送消息并关闭套接字(通过服务器的close方法)来测试我的聊天客户端应用程序。但是,似乎当我关闭套接字时,客户端线程仍在等待客户端输入。但是,我已经使用if子句来阻止它等待。这是我的测试:
@Test
public void testMessagesReceived() throws IOException
{
ServerSocket s = server.getSocket();
System.out.println(s);
mysocket = new Socket("127.0.0.1", 3000);
final PrintWriter stream = new PrintWriter(mysocket.getOutputStream(), true);
stream.println("Default room");
}
@AfterSuite
public void stopServer() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
server.stop();
}
但是,当server.stop()
执行并关闭套接字时,我在客户端线程中得到一个异常并且使用此套接字,这里:
public void acceptFromConsole() throws IOException {
if (!socket.isClosed()) {
final BufferedReader fromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String message;
while ((message = fromClient.readLine()) != null) { // Exception here
if (message.contains(TelnetUtilities.Quit.toString())) {
room.removeClient(id);
break;
}
}
这是完整的堆栈跟踪:
java.net.SocketException: Socket closed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
at sun.nio.cs.StreamDecoder.read(Unknown Source)
at java.io.InputStreamReader.read(Unknown Source)
at java.io.BufferedReader.fill(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at com.egt.chat.server.ClientContainer.acceptFromConsole(ClientContainer.java:40)
at com.egt.chat.server.ClientContainerRunnable.run(ClientContainerRunnable.java:28)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
在我看来,在一个线程中我关闭套接字,但是客户端线程没有看到套接字上的更改,并检查(!socket.isClosed())是否返回true并继续执行流程虽然我尝试阅读它当然抛出异常,我试图从一个封闭的套接字读取,有没有办法克服这个?
答案 0 :(得分:1)
您的代码正常运行。当您强行断开套接字时,您的代码就是while循环:
while ((message = fromClient.readLine()) != null) { // Exception here
if (message.contains(TelnetUtilities.Quit.toString())) {
room.removeClient(id);
break;
}
readLine()
正在等待传入的数据。如果你不关闭连接,它将永远等待新数据。然后关闭连接,readLine()
(或更好的底层socketRead
方法)现在认识到它无法从已关闭的套接字读取数据并引发异常。
因此,此异常是此时的预期异常。抓住它,快乐。
我会这样做:添加一个类似stopServerCalled
的布尔变量,默认为false
,并在调用true
时设置为stopServer()
。
try {
while ((message = fromClient.readLine()) != null) { // Exception here
if (message.contains(TelnetUtilities.Quit.toString())) {
room.removeClient(id);
break;
}
} catch (SocketException e) {
// check if this is an expected exception and if yes ignore it
if (!stopServerCalled)
throw e;
}