栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JDK中常见的Connection reset by peer、connection reset、broken pipe怎么来的

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JDK中常见的Connection reset by peer、connection reset、broken pipe怎么来的

大家可以先读下下面两篇,写的也比较清楚了。我再做总结扩展。
https://www.yisu.com/zixun/218302.html
http://lovestblog.cn/blog/2014/05/20/tcp-broken-pipe/

一、常见的TCP Socket异常码 ECONNRESET

收到对端的RST响应,程序会返回ECONNRESET错误码。比如对方是TCP主动关闭方(.close()),进入FIN_WAIT2之后,再向对端发数据会收到RST

EPIPE

向收到过RST的对端再次读写数据会立刻收到SIGPIPE信号并返回EPIPE。

SIGPIPE默认是会中止程序的,所以程序一般都捕获无视掉了,jvm也是。

两者定义处,c标准库

erro_list.c
615行可见 Connection reset by peer 字符串
360行可见 Broken pipe 字符串
说明这俩是系统层面的,所以不止在jdk,你可能在任何有用到socket通讯的组件比如redis、mq甚至ssh窗口看到这个异常

二、jni socket io函数对上述异常码的处理

open jdk8_b120

SocketInputStream


上图为jni socketRead0()函数处理异常码的代码段,其中JNU_ThrowByName函数会立刻抛出给定类型的异常,异常的message为第三个参数

可见,对于读操作,ECONNRESET或EPIPE都直接抛出了 sun.net.ConnectionResetException。此后,java对其又做了捕获包装:


java侧会捕获sun.net.ConnectionResetException,抛出 java.net.SocketException,message还是Connection reset。

SocketOutputStream


同样,上图为 socketWrite0() 函数,对于ECONNRESET jni还是会抛出sun.net.ConnectionResetException,java同样也会吃掉,抛出message一样类型变掉的异常:

上图可见,Java侧其他SocketException在本侧socket未关闭时会直接抛出,而Jni侧会通过NET_ThrowByNameWithLastError函数处理:


如果系统异常码有对应字符串,则使用异常码字符串,类型还是传入的类型,即最后会抛出 java.net.SocketException(“Broken pipe”)

jdk其他地方对这两个异常码的指名处理

搜索源码,发现还有PlainSocketImpl里avaliable0()会有对ECONNRESET的特殊处理,这个类是socket的具体实现。不过jdk默认已经不用这个实现了,而是NioSocketImpl:

三、JDK NIO 对异常的处理

通过第二节发现,抛的异常信息要么是Connection reset,要么是Broken Pipe,那Connection reset by peer是哪里抛出来的?
显然,除了指名处理这两个异常码的地方,有未指名,按默认逻辑抛出的地方,比如

FileDispatcherImpl

这是nio对fd做实际读写的地方,自然也有jni:


这里 return 行的 read、write就是linux经典的系统调用函数了,我们再来看它如何处理返回值:

对于异常码,除了EAGAIN和EINTR,其他没有特殊处理,直接抛出IOException,看红框函数名大家应该都能猜到这个是做什么的:

也就是说有错误码对应的系统异常字符串,就抛出 IOExcetion + 异常码对应字符串,比如Conenction reset by peer,没有则才根据读写抛出 Read / Write failed 信息的IOException(这里message不会带errno,是个坑的地方)

总结
  1. Connection reset 是由java捕获jni包装的系统异常后抛出的SocketException,出现的位置:
    a. 读操作,SocketInputStream,系统返回ECONNRESET或EPIPE
    b. 写操作,SocketOutputStream, 系统返回ECONNRESET
  2. Connection reset by peer 是由jni捕获系统ECONNRESET抛出的IOException,一般而言能说明系统用到了如nio的其他通讯框架
  3. Broken pipe 一定由EPIPE引起,可能是由系统层面抛出的IOException,也可能是jdk包装后的SocketException,出现的位置:
    a. 写操作,SocketOutputStream,SocketException
    b. FileDispatcherImpl read或write抛出的,IOException
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/820175.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号