您的位置:首页 > 编程语言 > Java开发

【java 中的connection reset 异常处理分析】

2013-08-07 10:11 323 查看
在Java中常看见的几个connection rest exception, Broken pipe, Connection reset,Connection reset by peer
  Socked reset case

  Linux中会有2个常见的sock reset 情况下的错误代码

  ECONNRESET

  该错误被描述为“connection reset by peer”,即“对方复位连接”,这种情况一般发生在服务进程较客户进程提前终止。当服务进程终止时会向客户 TCP 发送 FIN 分节,客户 TCP 回应 ACK,服务 TCP 将转入 FIN_WAIT2 状态。此时如果客户进程没有处理该 FIN (如阻塞在其它调用上而没有关闭 Socket 时),则客户 TCP 将处于 CLOSE_WAIT 状态。当客户进程再次向 FIN_WAIT2 状态的服务
TCP 发送数据时,则服务 TCP 将立刻响应 RST。一般来说,这种情况还可以会引发另外的应用程序异常,客户进程在发送完数据后,往往会等待从网络IO接收数据,很典型的如 read 或 readline 调用,此时由于执行时序的原因,如果该调用发生在 RST 分节收到前执行的话,那么结果是客户进程会得到一个非预期的 EOF 错误。此时一般会输出“server terminated prematurely”-“服务器过早终止”错误。

  EPIPE

  错误被描述为“broken pipe”,即“管道破裂”,这种情况一般发生在客户进程不理会(或未及时处理)Socket 错误,继续向服务 TCP 写入更多数据时,内核将向客户进程发送 SIGPIPE 信号,该信号默认会使进程终止(此时该前台进程未进行 core dump)。结合上边的 ECONNRESET 错误可知,向一个 FIN_WAIT2 状态的服务 TCP(已 ACK 响应 FIN 分节)写入数据不成问题,但是写一个已接收了 RST 的 Socket
则是一个错误。

  Java 中的socket input stream/output stream 的处理

  先看代码片段

  SocketInputStream.c

  [cpp]

  switch (errno) {

  case ECONNRESET:

  case EPIPE:

  JNU_ThrowByName(env, "sun/net/ConnectionResetException",

  "Connection reset");

  break;

  ....

  SocketOutputStream.c

  [cpp]

  if (errno == ECONNRESET) {

  JNU_ThrowByName(env, "sun/net/ConnectionResetException",

  "Connection reset");

  } else {

  NET_ThrowByNameWithLastError(env, "java/net/SocketException",

  "Write failed");

  }

  可以看到java 在读和写的情况关于EPIPE的情况是处理不一样的

  在read 的情况中,Reset 是全部抛出 ConnectionResetException, 提示的错误信息是 Connection Reset

  在write的情况下,Reset 对ECONNRESET的是抛出ConnectionResetException, 而对EPIPE 抛出的是SocketException ,错误信息是Broken pipe

  如何打印出信息Broken pipe

  SIGPIPE信号处理函数

  当在收到reset包后,如果在读写socket,会出现错误EPIPE,同时经常收到SIGPIPE信号

  在程序中可以看到java 并没有对write的情况下没有处理错误EPIPE,开始的时候错误的以抛出的异常是信号处理函数抛出的

更多精彩教程请关注:windows7系统下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: