java.net.SocketException: Thiết lập lại kết nối


126

Tôi nhận được lỗi sau khi cố gắng đọc từ một ổ cắm. Tôi đang làm điều readInt()đó InputStreamvà tôi nhận được lỗi này. Việc đọc tài liệu này cho thấy phần máy khách của kết nối đã đóng kết nối. Trong kịch bản này, tôi là máy chủ.

Tôi có quyền truy cập vào tệp nhật ký máy khách và nó không đóng kết nối và trên thực tế, tệp nhật ký của nó cho thấy tôi đang đóng kết nối. Vì vậy, có ai có một ý tưởng tại sao điều này đang xảy ra? Những gì khác để kiểm tra? Điều này có phát sinh khi có các tài nguyên địa phương có lẽ đang đạt đến ngưỡng?


Tôi lưu ý rằng tôi có dòng sau:

socket.setSoTimeout(10000);

ngay trước readInt() . Có một lý do cho điều này (câu chuyện dài), nhưng chỉ tò mò, có những trường hợp theo đó điều này có thể dẫn đến lỗi được chỉ định? Tôi có máy chủ đang chạy trong IDE của mình và tôi tình cờ để IDE của mình bị kẹt ở một điểm dừng và sau đó tôi nhận thấy các lỗi chính xác bắt đầu xuất hiện trong nhật ký của chính tôi trong IDE của tôi.

Dù sao, chỉ cần đề cập đến nó, hy vọng không phải là một cá trích đỏ. :-(


Bạn có dấu vết ngăn xếp từ cả hai bên? Bạn có thể mô tả kiến ​​trúc mạng nhiều hơn một chút? (Trên Internet hoang dã? Trên cùng một máy? Ở đâu đó ở giữa?) Nó có xảy ra mọi lúc không? Hay không liên tục?
Stu Thompson

Câu trả lời:


116

Có một số nguyên nhân có thể.

  1. Đầu kia đã cố tình thiết lập lại kết nối, theo cách mà tôi sẽ không ghi lại ở đây. Rất hiếm, và nói chung là không chính xác, đối với phần mềm ứng dụng để làm điều này, nhưng nó không phải là phần mềm thương mại.

  2. Thông thường hơn, nguyên nhân là do ghi vào một kết nối mà đầu kia đã đóng bình thường. Nói cách khác, một lỗi giao thức ứng dụng.

  3. Nó cũng có thể được gây ra bằng cách đóng một ổ cắm khi có dữ liệu chưa đọc trong bộ đệm nhận ổ cắm.

  4. Trong Windows, 'phần mềm gây ra hủy bỏ kết nối', không giống như 'thiết lập lại kết nối', là do các sự cố mạng gửi từ cuối của bạn. Có một bài viết cơ sở kiến ​​thức của Microsoft về điều này.


@MattLyons Cảm ơn. Có nhiều bài viết MSDN tốt hơn thế. Thành thật mà nói tôi thấy rằng một khó tin. Một kết nối thậm chí sẽ không tồn tại cho đến khi địa chỉ IP nguồn và đích chính xác được thiết lập. Các bài viết MSDN tôi đã thấy đề cập đến lỗi mạng liên tục trong thời gian kết nối.
Hầu tước Lorne

48

Thiết lập lại kết nối đơn giản có nghĩa là đã nhận được RST TCP. Điều này xảy ra khi đồng nghiệp của bạn nhận được dữ liệu mà nó không thể xử lý và có thể có nhiều lý do cho việc đó.

Đơn giản nhất là khi bạn đóng ổ cắm, sau đó ghi thêm dữ liệu vào luồng đầu ra. Bằng cách đóng ổ cắm, bạn nói với bạn bè rằng bạn đã nói xong và nó có thể quên kết nối của bạn. Khi bạn gửi thêm dữ liệu trên luồng đó, đồng nghiệp sẽ từ chối nó với RST để cho bạn biết rằng nó không nghe.

Trong các trường hợp khác, tường lửa can thiệp hoặc thậm chí chính máy chủ từ xa có thể "quên" kết nối TCP của bạn. Điều này có thể xảy ra nếu bạn không gửi bất kỳ dữ liệu nào trong một thời gian dài (2 giờ là thời gian chờ phổ biến) hoặc do thiết bị ngang hàng được khởi động lại và mất thông tin về các kết nối hoạt động. Gửi dữ liệu trên một trong những kết nối không còn tồn tại này cũng sẽ gây ra RST.


Cập nhật để đáp ứng với thông tin bổ sung:

Hãy xem xét kỹ việc xử lý của bạn SocketTimeoutException. Ngoại lệ này được nêu ra nếu vượt quá thời gian chờ được cấu hình trong khi bị chặn trên hoạt động của ổ cắm. Trạng thái của ổ cắm không bị thay đổi khi ném ngoại lệ này, nhưng nếu trình xử lý ngoại lệ của bạn đóng ổ cắm và sau đó cố gắng ghi vào nó, bạn sẽ ở trong điều kiện thiết lập lại kết nối. setSoTimeout()có nghĩa là cung cấp cho bạn một cách sạch sẽ để thoát ra khỏi một read()hoạt động có thể chặn vĩnh viễn, mà không làm những việc bẩn thỉu như đóng ổ cắm từ một luồng khác.


Không đúng trong một số khía cạnh. Việc thu gom và xử lý rác thải đều gây ra sự đóng cửa thích hợp, không phải là thiết lập lại, nhưng việc đóng lại theo sau bởi một người viết có thể tạo ra một thiết lập lại thay vì một EOS. SocketTimeoutExceptions chỉ được nêu ra nếu trình đọc đã đặt thời gian chờ đọc.
Hầu tước Lorne

Và nó không phải lúc nào cũng có nghĩa là một RST đã được nhận. Nó cũng có thể có nghĩa là một được tạo ra bởi phía này.
Hầu tước Lorne

17

Bất cứ khi nào tôi gặp vấn đề kỳ lạ như thế này, tôi thường ngồi xuống với một công cụ như WireShark và xem xét dữ liệu thô được truyền qua lại. Bạn có thể ngạc nhiên khi mọi thứ bị ngắt kết nối và bạn chỉ được thông báo khi bạn thử và đọc.


9

Xấu hổ khi nói điều đó, nhưng khi tôi gặp vấn đề này, đó chỉ là một lỗi mà tôi đã đóng kết nối trước khi tôi đọc tất cả dữ liệu. Trong trường hợp các chuỗi nhỏ được trả về, nó đã hoạt động, nhưng đó có lẽ là do toàn bộ phản hồi đã được đệm, trước khi tôi đóng nó.

Trong trường hợp số lượng văn bản được trả về lâu hơn, ngoại lệ đã bị ném, vì sau đó một bộ đệm đã quay trở lại.

Bạn có thể kiểm tra giám sát này. Hãy nhớ mở URL giống như một tệp, hãy chắc chắn đóng nó (giải phóng kết nối) sau khi nó đã được đọc đầy đủ.


9

Bạn nên kiểm tra dấu vết đầy đủ rất cẩn thận,

Tôi có một ứng dụng ổ cắm máy chủ và sửa một java.net.SocketException: Connection resettrường hợp.

Trong trường hợp của tôi, nó xảy ra trong khi đọc từ một Socketđối tượng clientSocket bị đóng kết nối vì một số lý do. (Mạng bị mất, tường lửa hoặc sự cố ứng dụng hoặc dự định đóng)

Trên thực tế, tôi đã thiết lập lại kết nối khi tôi gặp lỗi trong khi đọc từ đối tượng Socket này.

Socket clientSocket = ServerSocket.accept();
is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
int readed = is.read(); // WHERE ERROR STARTS !!!

Điều thú vị là for my JAVA Socketnếu một khách hàng kết nối với tôi ServerSocketvà đóng kết nối của nó mà không gửi bất kỳ is.read()cuộc gọi nào theo cách đệ quy. Có vẻ như là trong một vòng lặp vô hạn để đọc từ ổ cắm này, bạn cố gắng đọc từ một kết nối đóng. Nếu bạn sử dụng một cái gì đó như dưới đây cho hoạt động đọc;

while(true)
{
  Receive();
}

Sau đó, bạn nhận được một stackTrace một cái gì đó như bên dưới và trên

java.net.SocketException: Socket is closed
    at java.net.ServerSocket.accept(ServerSocket.java:494)

Những gì tôi đã làm chỉ là đóng ServerSocket và gia hạn kết nối của tôi và chờ kết nối máy khách tiếp theo

String Receive() throws Exception
{
try {                   
            int readed = is.read();
           ....
}catch(Exception e)
{
        tryReConnect();
        logit(); //etc
}


//...
}

Điều này xác nhận lại kết nối của tôi cho ổ cắm máy khách không xác định bị mất

private void tryReConnect()
        {
            try
            {
                ServerSocket.close();
                //empty my old lost connection and let it get by garbage col. immediately 
                clientSocket=null;
                System.gc();
                //Wait a new client Socket connection and address this to my local variable
                clientSocket= ServerSocket.accept(); // Waiting for another Connection
                System.out.println("Connection established...");
            }catch (Exception e) {
                String message="ReConnect not successful "+e.getMessage();
                logit();//etc...
            }
        }

Tôi không thể tìm thấy một cách khác bởi vì khi bạn nhìn thấy từ hình ảnh bên dưới, bạn không thể hiểu liệu kết nối có bị mất hay không mà không có try and catch, bởi vì mọi thứ dường như đúng. Tôi đã có được ảnh chụp này trong khi tôi đang nhận được Connection resetliên tục.

nhập mô tả hình ảnh ở đây


6

Tôi đã có những lỗi giống nhau. Tôi tìm thấy giải pháp cho vấn đề bây giờ. Vấn đề là chương trình máy khách đã hoàn tất trước khi máy chủ đọc các luồng.


Điều đó sẽ không gây ra ngoại lệ này trên chính nó.
Hầu tước Lorne

nếu System.exit (0) giết chương trình và không ai gọi socket.close () vì kết nối ở trạng thái xấu và không được đóng đúng cách. Vì vậy, nói đúng hơn là anh ta có một chương trình máy khách tắt mà không đóng ổ cắm;) đó là một điều xấu và cần được sửa chữa.
Dean Hiller

1
@DeanHiller Không, không. Hệ điều hành sẽ đóng ổ cắm giống như cách ứng dụng nên có.
Hầu tước Lorne

@EJP .... Tôi không chắc ... Tôi chỉ biết rằng chúng tôi có thể sao chép nó bằng System.exit nhưng tôi không nhớ OS / config vì cách đây khá lâu .... gọi socket.close ( ) trên máy chủ đã ngăn chặn thiết lập lại kết nối và nó hoạt động đúng hơn.
Dean Hiller

2
@DeanHiller Quá trình đọc đã thoát trước khi quá trình viết đã viết xong.
Hầu tước Lorne

4

Tôi gặp vấn đề này với một hệ thống SOA được viết bằng Java. Tôi đã chạy cả máy khách và máy chủ trên các máy vật lý khác nhau và chúng hoạt động tốt trong một thời gian dài, sau đó những thiết lập lại kết nối khó chịu đó xuất hiện trong nhật ký máy khách và không có gì lạ trong nhật ký máy chủ. Khởi động lại cả máy khách và máy chủ không giải quyết được vấn đề. Cuối cùng, chúng tôi đã phát hiện ra rằng heap ở phía máy chủ khá đầy đủ nên chúng tôi đã tăng bộ nhớ có sẵn cho JVM: đã giải quyết được vấn đề! Lưu ý rằng không có OutOfMemoryError trong nhật ký: bộ nhớ chỉ khan hiếm, không cạn kiệt.


2

Kiểm tra phiên bản Java của máy chủ của bạn. Đã xảy ra với tôi vì Weblogic 10.3.6 của tôi là trên JDK 1.7.0_75 trên TLSv1. Điểm cuối còn lại mà tôi đang cố gắng tiêu thụ là tắt mọi thứ bên dưới TLSv1.2.

Theo mặc định, Weblogic đã cố gắng đàm phán giao thức chia sẻ mạnh nhất. Xem chi tiết tại đây: Các vấn đề với cài đặt https.prot Protocol System property cho các kết nối HTTPS .

Tôi đã thêm ghi nhật ký SSL dài dòng để xác định TLS được hỗ trợ. Điều này cho thấy TLSv1 đã được sử dụng để bắt tay.
-Djavax.net.debug=ssl:handshake:verbose:keymanager:trustmanager -Djava.security.debug=access:stack

Tôi đã giải quyết vấn đề này bằng cách đẩy tính năng này ra sản phẩm tương thích JDK8 của chúng tôi, JDK8 mặc định là TLSv1.2. Đối với những người bị hạn chế đối với JDK7, tôi cũng đã thử nghiệm thành công một cách giải quyết cho Java 7 bằng cách nâng cấp lên TLSv1.2. Tôi đã sử dụng câu trả lời này: Cách bật TLS 1.2 trong Java 7


Rất cám ơn, bạn chỉ cho tôi một hướng đi mới để khắc phục vấn đề của tôi. và cuối cùng tôi đã tìm thấy nó là trường hợp !!!
karl li

1

Tôi cũng gặp vấn đề này với một chương trình Java đang cố gửi lệnh trên máy chủ thông qua SSH. Vấn đề là với máy thực thi mã Java. Nó không có quyền kết nối với máy chủ từ xa. Phương thức write () đã hoạt động ổn, nhưng phương thức read () đang ném java.net.SocketException: Thiết lập lại kết nối. Tôi đã khắc phục sự cố này bằng cách thêm khóa SSH máy khách vào các khóa máy chủ đã biết từ xa.


0

Theo kinh nghiệm của tôi, tôi thường gặp phải các tình huống sau đây;

  1. Nếu bạn làm việc trong một công ty doanh nghiệp, hãy liên hệ với nhóm bảo mật và mạng. Bởi vì trong các yêu cầu được thực hiện cho các dịch vụ bên ngoài, có thể cần phải cấp phép cho điểm cuối có liên quan.

  2. Một vấn đề khác là chứng chỉ SSL có thể đã hết hạn trên máy chủ nơi ứng dụng của bạn đang chạy.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.