簡體   English   中英

“軟件導致連接中止:套接字寫入錯誤”的官方原因

[英]Official reasons for "Software caused connection abort: socket write error"

鑒於此堆棧跟蹤片段

引起:java.net.SocketException:軟件導致連接中止:套接字寫入錯誤
在 java.net.SocketOutputStream.socketWrite0(本機方法)

我試圖回答以下問題:

  1. 什么代碼拋出這個異常? (JVM?/Tomcat?/我的代碼?)
  2. 是什么導致拋出這個異常?

關於#1:

Sun 的 JVM 源不包含此確切消息,但我認為文本軟件導致連接中止:套接字寫入錯誤來自SocketOutputStream的本機實現:

private native void socketWrite0(FileDescriptor fd, byte[] b, int off,
                 int len) throws IOException;

關於#2

我的猜測是它是在客戶端終止連接時引起的,在獲得完整響應之前(例如發送了一個請求,但在獲得完整響應之前,它被關閉/終止/離線)

問題:

  1. 上述假設是否正確(#1 和 #2)?
  2. 這可以與以下情況區別開來:“由於服務器端的網絡錯誤,無法寫入客戶端”? 還是會呈現相同的錯誤消息?
  3. 最重要的是否有官方文件(例如來自 Sun)說明上述內容?

我需要證明這個堆棧跟蹤是套接字客戶端的“錯誤”,並且服務器無法避免它。 (除了捕獲異常,或使用非 Sun JVM SocketOutputStream,盡管兩者都沒有真正避免客戶端已終止的事實)

當本地網絡系統中止連接時,例如當 WinSock 在數據重新傳輸失敗后關閉已建立的連接(接收器從不確認數據流套接字上發送的數據)時,可能會發生此錯誤。

請參閱此 MSDN 文章 另請參閱有關“軟件導致連接中止”的一些信息

java.net.SocketException在創建或訪問套接字(例如TCP )時出現錯誤時拋出。 這通常是在服務器終止連接(沒有正確關閉它)時引起的,因此在獲得完整響應之前。 在大多數情況下,這可能是由超時問題引起的(例如,響應花費了太多時間或服務器因請求而過載),或者客戶端發送了 SYN,但它沒有收到 ACK(連接終止的確認) . 對於超時問題,可以考慮增加超時值。

套接字異常通常帶有有關該問題的指定詳細消息。

詳細消息示例:

  • 軟件導致連接中止:接收失敗。

    該錯誤表示嘗試發送消息並且連接已被您的服務器中止。 如果在連接到數據庫時發生這種情況,這可能與使用不兼容的 Connector/J JDBC 驅動程序有關

    可能的解決方案:確保您的 CLASSPATH 中有正確的庫/驅動程序。

  • 軟件導致連接中止:connect。

    當連接到遙控器出現問題時,可能會發生這種情況。 例如, 由於病毒檢查器拒絕遠程郵件請求

    可能的解決方案:檢查病毒掃描服務是否阻塞了用於發出連接請求的端口。

  • 軟件導致連接中止:套接字寫入錯誤。

    可能的解決方案:確保將正確長度的字節寫入流。 因此,請仔細檢查您發送的內容。 看到這個線程

  • 對等方重置連接:套接字寫錯誤/對等方中止連接:套接字寫錯誤

    應用程序沒有檢查服務器端的保持連接是否超時。

    可能的解決方案:在從連接讀取之前確保 HttpClient 為非空。 E13222_01

  • 對等方重置連接。

    連接已被對等方(服務器)終止。

  • 連接重置。

    連接要么被客戶端終止,要么被連接的服務器端關閉,因為請求帶有請求。

    請參閱:是什么導致了我的 java.net.SocketException:連接重置?

當工作站/筆記本電腦上的企業防火牆妨礙連接時,我最常看到這種情況。

例如。 我在同一台機器上有一個服務器進程和一個客戶端進程。 服務器正在偵聽所有接口 (0.0.0.0),客戶端嘗試連接到公共/本地接口(注意不是環回接口 127.0.0.1)。

如果機器的網絡斷開(例如wifi關閉),則連接形成。 如果機器連接到公司網絡(直接或 vpn),則連接形成。

但是,如果機器連接到公共 wifi(或家庭網絡),則防火牆會啟動並終止連接。 在這種情況下,將客戶端連接到環回接口工作正常,只是不能連接到家庭/公共接口。

希望這可以幫助。

為了證明哪個組件出現故障,我將使用wireshark監視TCP/IP 通信並查看誰實際關閉了端口,超時也可能相關。

對於使用簡單的客戶端服務器程序並收到此錯誤的任何人來說,這是未關閉(或關閉到早期)輸入或輸出流的問題。

您是否檢查過 Tomcat 源代碼JVM 源代碼? 那可能會給你更多的幫助。

我認為你的總體思路很好。 我希望在您無法連接的情況下出現ConnectException 上面看起來很像它是客戶端驅動的。

我面臨着同樣的問題。
通常發生這種錯誤是由於客戶端已關閉其連接而服務器仍在嘗試在該客戶端上寫入。
因此,請確保您的客戶端打開其連接,直到服務器完成其輸出流。
還有一件事,不要忘記關閉輸入和輸出流。

希望這可以幫助。
如果仍然面臨問題,請在此處詳細介紹您的問題。

有一個 SSLPoke.bat(SSL 故障排除腳本)窗口腳本,盡管將正確的證書導入 cacerts trustore,但仍出現此錯誤。

C:\Java\jdk1.8.0_111\jre\lib\security>SSLPoke.bat

C:\Java\jdk1.8.0_111\jre\lib\security>"C:\jdk1.8.0_101\jre\bin\java" 
     `SSLPoke  tfs.corp.****.com  443`

java.net.SocketException: Software caused connection abort: recv failed
    `at java.net.SocketInputStream.socketRead0(Native Method)`
    `at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)`
    `at java.net.SocketInputStream.read(SocketInputStream.java:170)`
    `at java.net.SocketInputStream.read(SocketInputStream.java:141)`
    `at sun.security.ssl.InputRecord.readFully(InputRecord.java:465)`
    `at sun.security.ssl.InputRecord.read(InputRecord.java:503)`
    `at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973)`
    `at sun.security.ssl.SSLSocketImpl.performInitialHandshake
       (SSLSocketImpl.java:1375)`
    `at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:747)`
    `at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123)`
    `at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:138)`
    `at SSLPoke.main(SSLPoke.java:28)`

然后我檢查了一些關於我工作中一些網絡變化的舊筆記。 在某些情況下,我們需要添加 JVM 參數-Djava.net.preferIPv4Stack=true to make connections to certain machines我們網絡中的-Djava.net.preferIPv4Stack=true to make connections to certain machines以避免此錯誤。

C:\Java\jdk1.8.0_111\jre\lib\security>"C:\Java\jdk1.8.0_111\bin\java"  
    **-Djava.net.preferIPv4Stack=true**  SSLPoke tfs.corp.****.com 443

連接成功

SSLPoke 的代碼可以從這里下載: https ://gist.github.com/4ndrej/4547029

這個錯誤發生在我用 SoapUI 客戶端測試我的肥皂服務時,基本上我試圖獲得一個非常大的消息(> 500kb)並且 SoapUI 超時關閉了連接。

在 SoapUI 上轉到:

文件-->首選項--套接字超時(毫秒)

...並輸入一個較大的值,例如 180000(3 分鍾),這不是解決您問題的完美方法,因為該文件實際上太大了,但至少您會有響應。

在另一個客戶端關閉連接

就我而言,錯誤是:

java.net.SocketException: Software caused connection abort: recv failed

它是在 eclipse 中調試訪問 H2 數據庫的 Java 應用程序時收到的。 錯誤的根源是我最初使用 SQuirreL 打開數據庫以手動檢查完整性。 我確實使用該標志啟用到同一個數據庫的多個連接(即AUTO_SERVER=TRUE ),因此從 java 連接到數據庫沒有問題。

過了一會兒——這是一個很長的Java進程——我決定關閉SQuirreL以釋放資源時出現錯誤。 看起來好像 SQuirreL 是“擁有”數據庫服務器實例的人,並且它已通過 SQuirreL 連接關閉。

重新啟動 Java 應用程序沒有再次產生錯誤。

配置

  • Windows 7的
  • 日食開普勒
  • 松鼠 3.6
  • org.h2.Driver 版本 1.4.192

在下面解釋的情況下,客戶端會拋出這樣的異常:

服務器被要求對客戶端證書進行身份驗證,但客戶端提供了擴展密鑰用法不支持客戶端身份驗證的證書,因此服務器不接受客戶端的證書,然后關閉連接。

我的服務器在過去 2 天內拋出了這個異常,我通過移動斷開連接功能解決了這個問題:

outputStream.close();
inputStream.close();
Client.close();

到列表線程的末尾。 如果它會幫助任何人。

給定此堆棧跟蹤代碼段

引起原因:java.net.SocketException:軟件導致連接中止:套接字寫入錯誤
在java.net.SocketOutputStream.socketWrite0(本機方法)

我試圖回答以下問題:

  1. 哪些代碼引發此異常? (JVM?/ Tomcat?/我的代碼?)
  2. 是什么導致引發此異常?

關於#1:

Sun的JVM源不包含此確切消息,但我認為文本軟件導致連接中止:套接字寫入錯誤來自SocketOutputStream的本機實現:

private native void socketWrite0(FileDescriptor fd, byte[] b, int off,
                 int len) throws IOException;

關於#2

我的猜測是,這是由於客戶端在獲得完整響應之前(例如,發送了一個請求,但是在獲得完整響應之前,它已關閉/終止/脫機)終止了連接。

問題:

  1. 以上假設是否正確(#1和#2)?
  2. 是否可以與以下情況區別開來:“由於服務器端發生網絡錯誤而無法寫入客戶端”? 還是會呈現相同的錯誤消息?
  3. 最重要的是否有正式文件(例如來自Sun的文件)說明上述內容?

我需要證明此堆棧跟蹤是套接字客戶端的“故障”,並且服務器無法做任何事情來避免它。 (捕獲異常或使用非Sun JVM SocketOutputStream除外,盡管兩者都不能真正避免客戶端已終止的事實)

就我而言,我開發了客戶端和服務器端,但有一個例外:

原因:錯誤編組參數; 嵌套異常為:java.net.SocketException:軟件導致連接中止:套接字寫入錯誤

當客戶端和服務器中的類不同時。 我不在客戶端下載服務器的類(接口),我只是在項目中添加相同的文件。 但路徑必須完全相同。 例如,在服務器項目上,我有帶有一些 serviceInterface 和實現的 java\\rmi\\services 包,我必須在客戶端項目上創建相同的包。 例如,如果我通過 java/rmi/server/services 更改它,則會出現上述異常。 如果客戶端和服務器之間的接口版本不同,則相同的異常(即使無意中添加了一個空行......我認為 rmi 制作了一種類的哈希來檢查版本......我不知道......如果可以的話幫助 ...

我在模擬其余 API 調用時遇到了與 wireMock 相同的問題。 早些時候我是這樣定義服務器的:

WireMockServer wireMockServer = null;

但它應該定義如下:

@Rule 
public WireMockRule wireMockRule = new WireMockRule(8089);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM