Java 套接字关闭时不会引发异常
关闭服务器套接字时,即使在输出流上写入,并且服务器套接字已关闭之后,客户端也不会收到任何异常 给出以下类来测试:Java 套接字关闭时不会引发异常,java,sockets,Java,Sockets,关闭服务器套接字时,即使在输出流上写入,并且服务器套接字已关闭之后,客户端也不会收到任何异常 给出以下类来测试: public class ModemServerSocket { public static void main(String[] args) throws IOException, InterruptedException { ServerSocket serverSocket = new ServerSocket(63333); Sock
public class ModemServerSocket {
public static void main(String[] args) throws IOException, InterruptedException {
ServerSocket serverSocket = new ServerSocket(63333);
Socket client = serverSocket.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8"));
String s;
while ((s = reader.readLine()) != null) {
System.out.println(s);
if (s.equals("q")) {
break;
}
}
serverSocket.close();
}
}
公共类ModemClientSocket{
public static void main(String[] args) throws IOException, InterruptedException {
Socket socket = new Socket("localhost", 63333);
PrintWriter writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8"), true);
String[] sArray = {"hello", "q", "still there?"};
for (String s : sArray) {
writer.println(s);
if (s.equals("q")) {
Thread.sleep(5 * 1000);
}
}
System.out.println("Whoop. No exception. The client didn't notice.");
}
}
我所做的是启动ModemServerSocket应用程序,然后启动ModemClientSocket应用程序
模式服务器套接字输出:
hello
q
Whoop. No exception. The client didn't notice.
ModemClientSocket输出:
hello
q
Whoop. No exception. The client didn't notice.
这是预期的行为吗?为什么会发生这种情况
然而,我做了另一个测试,关闭ModemClientSocket,ModemServerSocket尝试从InputStream读取数据。在这种情况下,我得到了一个java.net.SocketException,这正是我所期望的。奇怪的是,PrintWriter(OutputStream)没有发生这种情况,并且没有引发异常
我使用Java 1.6.0 Update 26进行测试。我认为关闭ServerSocket只意味着不会接受新的连接——它不会关闭已设置的连接(您需要在ModemServerSocket中调用client.close()来完成此操作).我认为关闭ServerSocket只意味着不接受新的连接——这并不意味着关闭已经设置好的连接(您需要在ModemServerSocket中调用client.close()来实现这一点)。引用下面PrintWriter的JDK文档 此类中的方法从不抛出I/O异常,尽管它的一些构造函数可能会抛出I/O异常。客户端可以通过调用checkError()查询是否发生了任何错误
引用下面PrintWriter的JDK文档 此类中的方法从不抛出I/O异常,尽管它的一些构造函数可能会抛出I/O异常。客户端可以通过调用checkError()查询是否发生了任何错误
根据我运行的一些测试,即使您不使用PrintWriter,而是直接写入socket.getOutputStream(),我认为服务器关闭其socket时不一定会出现异常,但如果调用write()足够多次,似乎最终会出现异常 请注意,根据客户端和服务器是否在同一台计算机上,有时行为会有所不同。在本地运行时,“SocketException:Break pipe”异常发生之前,似乎需要更少的写入 如果您想真正检测到套接字已关闭,则需要从中读取,并检查读取是否返回-1。(当然,还要处理任何异常) 例如:
if (socket.getInputStream().read(bytearray) < 0)
break;
if(socket.getInputStream().read(bytearray)<0)
打破
如果服务器没有发送任何东西,您可以通过调用socket.setSortimeout(1)并处理/忽略SocketTimeoutException来解决问题,但“正确”的方法可能是从开始而不是从socket开始,这样您就可以使用一个函数,当可以调用read()方法时,它会通知您
顺便说一句,serverSocket.close()行有点误导人,可能应该是client.close()。但是,该类随后立即退出,因此所有套接字都将被关闭。基于我运行的一些测试,即使您不使用PrintWriter,而是直接写入socket.getOutputStream(),我认为当服务器关闭其套接字时,不能保证会出现异常,但如果调用write()足够多次,似乎最终会出现异常 请注意,根据客户端和服务器是否在同一台计算机上,有时行为会有所不同。在本地运行时,“SocketException:Break pipe”异常发生之前,似乎需要更少的写入 如果您想真正检测到套接字已关闭,则需要从中读取,并检查读取是否返回-1。(当然,还要处理任何异常) 例如:
if (socket.getInputStream().read(bytearray) < 0)
break;
if(socket.getInputStream().read(bytearray)<0)
打破
如果服务器没有发送任何东西,您可以通过调用socket.setSortimeout(1)并处理/忽略SocketTimeoutException来解决问题,但“正确”的方法可能是从开始而不是从socket开始,这样您就可以使用一个函数,当可以调用read()方法时,它会通知您
顺便说一句,serverSocket.close()行有点误导,可能应该是client.close()。但是,该类随后立即退出,因此所有套接字都将关闭。感谢您提到read()比write()更可靠关于捕获连接错误。我认为.flush会通过一个异常,但它没有,相反,它一直在向套接字写入,就好像它是活动的一样。然后,我使用read()来阻止线程,如果其他套接字死了。然后,我使用read+setsotimeout,它工作得很好。感谢Hanks提到read()比write()更可靠关于捕获连接错误。我认为.flush会通过一个异常,但它没有,相反,它一直在向套接字写入,就好像它是活动的一样。然后我使用read(),如果其他套接字死了,它会阻止线程。然后我使用read+setsotimeout,它工作得很好。谢谢