java socket异常java.net.SocketException

  最近看到java socket,在连接已关闭下,调用read或write会报java.net.SocketException异常,对这些异常产生原因我进行了一下详细理解。

  首先,得理解下连接关闭要分为两种情况:有序释放连接和异常终止。

  有序释放连接从TCP传输层看理解为两个阶段:A决定停止向B发数据,于是A主动发送fin信息给B,B的TCP协议栈收完fin之前A发来的所有数据后,会收到fin信息,于是B就知道A之后没有数据会再过来了,一但B端读取完fin信息之前的所有数据,B再调用read读取就会返回-1,-1用来表明流的end。这一个过程被称为TCP半关闭,此时主动关闭方A应该仍然能正常接收B的数据。同样的,由B主动向A发送fin,完成另一半的关闭后,这样整个TCP连接就有序释放,彻底关闭了。

  异常终止使用RST(Reset)消息,任何一方发出RST,就意味着连接将中止,任意一端TCP发送或接收缓冲区的信息将被TCP协议栈丢弃

  默认的linger配置是走第一个有序释放连接。但是有个特别需要注意的一点:java的Socket.close()和TCP FIN消息语义是不一致的, TCP的FIN意味着只是关闭了主动方一侧的写,而应用层java的Socket.close() 却意味着直接结束了读和写。这个区别会带来一个有意思的异常java.net.SocketException。

  当A调用socket.close,发送fin消息给B后,此时B仍然发送数据给A,会产生什么情况?从TCP层面来看,这是完全可以的,因为只是半关闭。但是调用了java socket.close意味着应用层已经不能再接收数据了,这个socket已经完全关闭了。此时A的TCP协议栈会发送RST消息给B强制终止连接。收到RST后,此时若B再次发送数据给A,B就会报java.net.SocketException异常(B第一次write,TCP协议栈收到RST,但是应用无感知,第二次write,B就会抛出异常)。

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值