浅谈java socket的正确关闭姿势

网友投稿 272 2023-01-07

浅谈java socket的正确关闭姿势

java socket对应的是网络协议中的tcp,tcp的三次握手、四次挥手、11中状态什么的这里就不说了,不知道大家平常使用socket的时候如果不注意的情况下,会不会遇到各种异常报错。

例如:

java.net.SocketException:socket is closed

错误提示的出现场景:

自己主动关闭了socket,但是之后还从里面读写数据

Software caused connection abort: socket write error

错误提示的出现场景:

对方已经关闭socket,依旧向对方写数据

connection reset (by peer)

错误提示出现的场景:

一端socket被关闭,另一端仍然发送数据,发送的第一个数据包 connection reset by peer

一端socket退出,退出时为关闭连接,另一端读数据 connection reset

所以在使用socket时,需要约定好双方读写完成的条件,然后关闭输入输出流:

socket.shutdownInput();

socket.shutdownOutput();

即当一方写入完成后,调用shutdownOutput关闭输出流,这时候对方的read方法就会返回-1,这时候对方就知道你写完了,对方可以关闭输入流,然后等待对方写入完成调用shutdownOutput后己方再调用shutdownInput,双方就正常关闭了输入输出流,这时候socket就不会出现异常了。

下面是一个socket交互的例子:

server端

public class OioServer {

public static void main(String[] args) throws IOException {

ServerSocket serverSocket = new ServerSocket(8080);

while (true) {

Socket socket = serverSocket.accept();

System.out.println("socket = " + socket);

new Thread(() -> {

try {

InputStream in = socket.getInputStream();

OutputStream out = socket.getOutputStream();

out.write("hello! I get your message that is follow".getBytes(Charset.forName("UTF-8")));

byte[] buf = new byte[1024];

int len;

while ((len = in.read(buf)) != -1) {

System.out.print(new String(buf, 0, len, Charset.forName("UTF-8")));

out.write(buf, 0, len);

}

out.write("\n end \n".getBytes(Charset.forName("UTF-8")));

out.flush();

socket.shutdownInput();

socket.shutdownOutput();

} catch (IOException e) {

e.printStackTrace();

}finally {

try {

socket.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}).start();

}

}

}

client端

public class OioClient {

public static void main(String[] args) throws IOException {

Socket socket = new Socket("127.0.0.1", 8080);

InputStream in = socket.getInputStream();

new Thread(() -> {

BufferedInputStream bufferIn = new BufferedInputStream(in);

byte[] buf = new byte[1024];

try {

int len;

while ((len = bufferIn.read(buf)) != -1) {

System.out.print(new String(buf, 0, len, Charset.forName("UTF-8")));

}

}catch (Exception e) {

e.printStackTrace();

}

try {

socket.shutdownInput();

socket.close();

} catch (IOException e) {

e.printStackTrace();

}

}).start();

OutputStream out = socket.getOutputStream();

int cout = 10;

while (cout-- > 0) {

out.write(("this time is " + System.currentTimeMillis() + "\n").getBytes("UTF-8"));

}

socket.shutdownOutput();

}

}

java socket - 半关闭

通常,使用关闭输出流来表示输出已经结束。但在进行网络通信时则不能这样做。因为我们关闭输出流时,该输出流对应的Socket也将随之关闭,这样程序将无法再从该socket中读取数据。

为了应付这种情况,socket提供了两个ilegUov半关闭的方法用来只关闭socket的输入流或者输出流,用以表示输出数据已经发送完成。

方法详情:

shutdownInput():关闭该socket的输入流,程序还可以通过该socket的输出流输出数据;

shutdownOutput():关闭该socket的输出流,程序还可以通过该socket的输入流读取数据。

当调用shutdownInput()或shutdownOutput()方法关闭输入流或输出流后,该socket处于半关闭状态。

此时可以使用isInputShutdown()或isOutputShutdown()来判断该socket是否处于半读状态或半写状态。

需要注意的是,即使同一个socket先后调用shutdownInput()和shutdownInput()方法,该socket实例仍然没有被关闭,只是该socket既不能输出数据也不能读取数据而已。

当调用shutdownInput()或shutdownOutput()方法关闭了输入流或输出流之后,该socket无法再次打开输出流或输入流,因此这种做法不适合需要保持持久通信状态的交互式应用。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:洛阳快递物流查询单号查不到(洛阳市物流信息查询)
下一篇:解决spring @ControllerAdvice处理异常无法正确匹配自定义异常
相关文章

 发表评论

暂时没有评论,来抢沙发吧~