it-swarm-vi.tech

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

Tôi nhận được lỗi sau khi cố gắng đọc từ một ổ cắm. Tôi đang thực hiện readInt() về điều đó InputStream và tôi đang gặp phải lỗi này. Việc xem lại 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? Còn gì để 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 mà đ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ờ để lại IDE bị kẹt ở một điểm dừng và sau đó tôi nhận thấy chính xác các lỗi tương tự bắt đầu xuất hiện trong nhật ký của chính tôi trong IDE của mình.

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

101
Darryl

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.

100
user207421

Thiết lập lại kết nối đơn giản có nghĩa là đã nhận được TCP RST. Đ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" về 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 để phản hồi thông tin bổ sung :

Hãy xem xét kỹ việc xử lý SocketTimeoutException của bạn. 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 hoạt động read() 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.

41
erickson

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.

13
GEOCHET

Xấu hổ khi nói điều đó, nhưng khi tôi gặp vấn đề này, đó chỉ đơn giản 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 đủ.

8
Scott S

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 trường hợp Java.net.SocketException: Connection reset.

Trong trường hợp của tôi, điều đó xảy ra trong khi đọc từ một đối tượng clientSocket Socket 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 Socket nếu một khách hàng kết nối với ServerSocket của tôi và đóng kết nối của nó mà không gửi bất cứ thứ gì is.read() tự gọi một cách đệ quy. 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ư 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à làm mới kết nối của mình 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ư đều đúng. Tôi đã nhận được ảnh chụp nhanh này trong khi tôi nhận được Connection reset liên tục.

enter image description here

7
Davut Gürbüz

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.

5
kml_ckr

Tôi gặp vấn đề này với 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.

4
Pino

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 tốt, 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 của máy khách vào các khóa máy chủ đã biết từ xa.

1
pmartin8

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 đã có 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 Thuộc tính hệ thống 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

0
behold