JAVA NIO Connection reset by peer 异常

怼烎@ 2022-01-14 08:19 392阅读 0赞

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

客户端主动断开与服务端的连接,但是如果客户端掉线,服务端就接收不到了。。

异常信息

  1. java.io.IOException: Connection reset by peer
  2. at java.base/sun.nio.ch.FileDispatcherImpl.read0(Native Method)
  3. at java.base/sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39)
  4. at java.base/sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:276)
  5. at java.base/sun.nio.ch.IOUtil.read(IOUtil.java:245)
  6. at java.base/sun.nio.ch.IOUtil.read(IOUtil.java:223)
  7. at java.base/sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:358)
  8. at space.pankui.nio.chat.ChatNIOServer.read(ChatNIOServer.java:123)
  9. at space.pankui.nio.chat.ChatNIOServer.start(ChatNIOServer.java:100)
  10. at space.pankui.nio.chat.ChatNIOServer.main(ChatNIOServer.java:27)
  11. 客户端掉线了....
  12. /**
  13. * 读取客户端消息
  14. */
  15. private String read(SelectionKey key) {
  16. SocketChannel socketChannel = (SocketChannel) key.channel();
  17. String readResult = "客户端发送信息:";
  18. try {
  19. ByteBuffer readBuffer = ByteBuffer.allocate(256);
  20. socketChannel.configureBlocking(false);
  21. int read = 0;
  22. try {
  23. read = socketChannel.read(readBuffer);
  24. } catch (IOException e) {
  25. System.out.println("客户端掉线了....");
  26. // https://stackoverflow.com/questions/8658118/when-is-java-io-ioexceptionconnection-reset-by-peer-thrown
  27. // The remote forcibly closed the connection, cancel
  28. // the selection key and close the channel.
  29. // 需要在这里做判断
  30. key.cancel();
  31. socketChannel.close();
  32. return "客户端掉线";
  33. }
  34. //这个方法只能侦测到客户端主动断开与服务端的连接,但是如果客户端掉线,服务端就接收不到
  35. if (read == -1) {
  36. socketChannel.close();
  37. key.cancel();
  38. }
  39. readBuffer.flip();
  40. String result = new String(readBuffer.array(), StandardCharsets.UTF_8).trim();
  41. System.out.println("客户端发送信息:" + result);
  42. return readResult + result;
  43. } catch (IOException e) {
  44. e.printStackTrace();
  45. }
  46. return readResult;
  47. }

注意 如果你的代码有读和写,在客户端掉线之后

  1. key.cancel();
  2. socketChannel.close();

当你在之后还有调用 SelectionKey 需要判断是否 有效。

  1. while (iterator.hasNext()) {
  2. SelectionKey selectionKey = iterator.next();
  3. iterator.remove();
  4. // 每个都需要判断是否有效,因为客户端可能掉线了,然后就释放了
  5. if (selectionKey.isValid() && selectionKey.isAcceptable()) {
  6. this.accept(selectionKey);
  7. }
  8. if (selectionKey.isValid() && selectionKey.isReadable()) {
  9. this.read(selectionKey);
  10. }
  11. if (selectionKey.isValid() && selectionKey.isWritable()) {
  12. this.write(selectionKey);
  13. }
  14. }

参考 https://stackoverflow.com/a/28645076/4712855

下面这里给的方法解决不了客户端掉线问题 https://blog.csdn.net/lopper/article/details/6645905

代码来源: https://blog.csdn.net/weixin_37910453/article/details/86662228

转载于:https://my.oschina.net/u/1394615/blog/3053331

发表评论

表情:
评论列表 (有 0 条评论,392人围观)

还没有评论,来说两句吧...

相关阅读