一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - java中的connection reset 異常處理分析

java中的connection reset 異常處理分析

2020-09-05 12:05raintungli Java教程

本文主要介紹了java中的connection reset 異常處理分析的相關資料,具有很好的參考價值。下面跟著小編一起來看下吧

在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

java" id="highlighter_184367">
?
1
2
3
4
5
6
7
switch (errno) {
case ECONNRESET:
case EPIPE:
  JNU_ThrowByName(env, "sun/net/ConnectionResetException",  
  "Connection reset");
  break;
         ....

SocketOutputStream.c

?
1
2
3
4
5
6
7
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,開始的時候錯誤的以拋出的異常是信號處理函數拋出的

先來看一下關于信號SIGPIPE的處理函數,在Linux::install_signal_handlers 里面調用函數

?
1
2
3
4
5
6
set_signal_handler(SIGSEGV, true);
set_signal_handler(SIGPIPE, true);
set_signal_handler(SIGBUS, true);
set_signal_handler(SIGILL, true);
set_signal_handler(SIGFPE, true);
set_signal_handler(SIGXFSZ, true);

而函數set_signal_handler,中對對應的信號處理函數是signalHandler

?
1
2
3
4
5
6
7
sigAct.sa_handler = SIG_DFL;
 if (!set_installed) {
  sigAct.sa_flags = SA_SIGINFO|SA_RESTART;
 } else {
  sigAct.sa_sigaction = signalHandler;
  sigAct.sa_flags = SA_SIGINFO|SA_RESTART;
 }

最終還是調用了函數 JVM_handle_linux_signal

在X86架構下, 函數JVM_handle_linux_signal

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
extern "C" int
JVM_handle_linux_signal(int sig,
            siginfo_t* info,
            void* ucVoid,
            int abort_if_unrecognized) {
 ucontext_t* uc = (ucontext_t*) ucVoid;
 
 Thread* t = ThreadLocalStorage::get_thread_slow();
 
 SignalHandlerMark shm(t);
 
 // Note: it's not uncommon that JNI code uses signal/sigset to install
 // then restore certain signal handler (e.g. to temporarily block SIGPIPE,
 // or have a SIGILL handler when detecting CPU type). When that happens,
 // JVM_handle_linux_signal() might be invoked with junk info/ucVoid. To
 // avoid unnecessary crash when libjsig is not preloaded, try handle signals
 // that do not require siginfo/ucontext first.
 
 if (sig == SIGPIPE || sig == SIGXFSZ) {
  // allow chained handler to go first
  if (os::Linux::chained_handler(sig, info, ucVoid)) {
   return true;
  } else {
   if (PrintMiscellaneous && (WizardMode || Verbose)) {
    char buf[64];
    warning("Ignoring %s - see bugs 4229104 or 646499219",
        os::exception_name(sig, buf, sizeof(buf)));
   }
   return true;
  }
 }
...
}

對信號SIGPIPE 使用了chained handler處理,也就是使用了系統的原來信號處理函數,也就證明了異常并不是信號處理函數拋出的

NET_ThrowByNameWithLastError函數

既然不是信號處理函數拋出的異常,繼續查看原來的outputstream的程序

?
1
2
3
4
5
6
7
if (errno == ECONNRESET) {
          JNU_ThrowByName(env, "sun/net/ConnectionResetException",
            "Connection reset");
    } else {
      NET_ThrowByNameWithLastError(env, "java/net/SocketException"
      "Write failed");
    }

也就是else 的情況,那么針對EPIPE的錯誤,java拋出的socketexception, 錯誤信息是Write failed ,事實上我們可以看到的卻是SockedException,異常對對上了, 但信息顯示是Broken pipe,而不是Write failed.

關鍵點就在函數 NET_ThrowByNameWithLastError

?
1
2
3
4
5
6
7
void
NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
          const char *defaultDetail) {
  char errmsg[255];
  sprintf(errmsg, "errno: %d, error: %s\n", errno, defaultDetail); 
  JNU_ThrowByNameWithLastError(env, name, errmsg); 
}

函數JNU_ThrowByNameWithLastError

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
JNIEXPORT void JNICALL
JNU_ThrowByNameWithLastError(JNIEnv *env, const char *name,
         const char *defaultDetail)
{
  char buf[256];
  int n = JVM_GetLastErrorString(buf, sizeof(buf));
 
  if (n > 0) {
  jstring s = JNU_NewStringPlatform(env, buf);
  if (s != NULL) {
    jobject x = JNU_NewObjectByName(env, name,
            "(Ljava/lang/String;)V", s);
    if (x != NULL) {
    (*env)->Throw(env, x);
    }
  }
  }
  if (!(*env)->ExceptionOccurred(env)) {
  JNU_ThrowByName(env, name, defaultDetail);
  }
}

程序可以看到先顯示 JVM_GetLastErrorString 的信息,如果信息是空的情況下才顯示defaultDetail的異常信息,也就是開始對應的Write failed!

JVM_GetLastErrorString 使用hpi::lasterror ,也就是函數sysGetLastErrorString 在linux和solaris 是一樣的

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int
sysGetLastErrorString(char *buf, int len)
{
  if (errno == 0) {
  return 0;
  } else {
  const char *s = strerror(errno);
  int n = strlen(s);
  if (n >= len) n = len - 1;
  strncpy(buf, s, n);
  buf[n] = '\0';
  return n;
  }
}

原來是strerror(errno) ,也就是直接顯示linux kernel 對應這個error number 的錯誤內容

結論:Broken pipe 是內核對應的錯誤信息,并不是java自己提供的信息

以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持服務器之家!

原文鏈接:http://blog.csdn.net/raintungli/article/details/8625126

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产成人福利美女观看视频 | 国产成人福利美女观看视频 | 91精品天美精东蜜桃传媒免费 | 国产亚洲精品高清在线 | 91短视频在线观看2019 | 无码天堂亚洲国产AV久久 | 欧美成人禁片在线观看俄罗斯 | 美女18隐私羞羞视频网站 | 欧美伊人影院 | 日本大乳护士的引诱图片 | 国产精品久久久久毛片真精品 | 美女岳肉太深了使劲 | 湿好紧太硬了我太爽了 | 国产三级跑 | 精品无码国产污污污免费网站2 | a一区二区三区视频 | 精品午夜寂寞影院在线观看 | 免费观看一级特黄三大片视频 | 亚洲AV久久无码精品九号软件 | 日韩欧美亚洲国产高清在线 | 久久久久伊人 | 农夫69小说小雨与农村老太 | 丰满肥臀风间由美357在线 | 国内精品视频一区二区三区八戒 | 精品国产乱码久久久久久免费流畅 | 都市风流贵妇激情 | 操美女b| 摸逼小说 | 臀控福利大臀的网站 | 成人涩涩屋福利视频 | 9999热视频| 国产成人精品视频频 | 国产一卡2卡3卡四卡精品网 | 美女脱了内裤打开腿让男人图片 | 精品人伦一区二区三区潘金莲 | 公妇乱淫在线播放免费观看 | chaopeng在线观看 | 日本网络视频www色高清免费 | 日本xxxx19视频 | 国产极品麻豆91在线 | 精品久久成人免费第三区 |