[java] java.net.SocketException : 연결 재설정

소켓에서 읽으려고하면 다음 오류가 발생합니다. 내가하고있어 readInt()이에 InputStream, 나는이 오류를 얻고있다. 문서를 숙독하면 연결의 클라이언트 부분이 연결을 닫았 음을 알 수 있습니다. 이 시나리오에서 나는 서버입니다.

클라이언트 로그 파일에 액세스 할 수 있지만 연결이 닫히지 않고 실제로 로그 파일에 연결을 닫고 있다고 제안됩니다. 왜 이런 일이 일어나는지 아는 사람이 있습니까? 또 무엇을 확인해야합니까? 임계 값에 도달 한 로컬 리소스가있을 때 발생합니까?


다음 줄이 있습니다.

socket.setSoTimeout(10000);

받는 사람 직전 readInt(). 이에 대한 이유 (긴 이야기)가 있지만 궁금한 점이 있습니다. 이로 인해 표시된 오류가 발생할 수있는 상황이 있습니까? IDE에서 서버를 실행하고 있는데, IDE를 중단 점에 멈춰 놓은 후 IDE의 내 로그에 똑같은 오류가 나타나기 시작하는 것을 발견했습니다.

어쨌든, 그것을 언급하기 만하면 붉은 청어가 아니길 바랍니다. 🙁



답변

몇 가지 가능한 원인이 있습니다.

  1. 다른 쪽 끝은 여기에 문서화하지 않을 방식으로 의도적으로 연결을 재설정했습니다. 응용 프로그램 소프트웨어가이 작업을 수행하는 것은 드물고 일반적으로 올바르지 않지만 상용 소프트웨어에 대해서는 알려지지 않았습니다.

  2. 더 일반적으로 다른 쪽 끝이 이미 정상적으로 닫힌 연결에 쓰기 때문에 발생합니다. 즉, 응용 프로그램 프로토콜 오류입니다.

  3. 소켓 수신 버퍼에 읽지 않은 데이터가있을 때 소켓을 닫으면 발생할 수도 있습니다.

  4. Windows에서 ‘연결 재설정’과 다른 ‘소프트웨어로 인한 연결 중단’은 사용자 쪽에서 보내는 네트워크 문제로 인해 발생합니다. 이에 대한 Microsoft 기술 자료 문서가 있습니다.


답변

연결 재설정은 단순히 TCP RST가 수신되었음을 의미합니다. 이는 피어가 처리 할 수없는 데이터를 수신 할 때 발생하며 그 이유는 다양 할 수 있습니다.

가장 간단한 방법은 소켓을 닫은 다음 출력 스트림에 더 많은 데이터를 쓰는 것입니다. 소켓을 닫음으로써 당신은 당신이 말을 끝냈 음을 동료에게 알 렸으며 당신의 연결을 잊을 수 있습니다. 어쨌든 해당 스트림에서 더 많은 데이터를 보내면 피어는 RST를 사용하여 데이터를 거부하여 수신 중이 아님을 알립니다.

다른 경우에는 개입 방화벽이나 원격 호스트 자체가 TCP 연결을 “잊을”수 있습니다. 오랜 시간 동안 데이터를 보내지 않거나 (2 시간이 일반적인 제한 시간 임) 피어가 재부팅되어 활성 연결에 대한 정보가 손실 되었기 때문에 발생할 수 있습니다. 이러한 존재하지 않는 연결 중 하나에서 데이터를 전송하면 RST도 발생합니다.


추가 정보에 대한 업데이트 :

의 당신의 처리를 자세히 살펴 보자 SocketTimeoutException. 소켓 작업에서 차단 된 동안 구성된 제한 시간이 초과되면이 예외가 발생합니다. 이 예외가 throw 될 때 소켓 자체의 상태는 변경되지 않지만 예외 처리기가 소켓을 닫은 다음 소켓에 쓰려고하면 연결 재설정 상태가됩니다. 다른 스레드에서 소켓을 닫는 것과 같은 더러운 작업을 수행하지 않고 영원히 차단 될 수 setSoTimeout()있는 read()작업 을 중단 할 수있는 깨끗한 방법을 제공합니다 .


답변

이와 같은 이상한 문제가있을 때마다 보통 WireShark 와 같은 도구 를 사용하여 앞뒤로 전달되는 원시 데이터를 확인합니다. 어디에서 연결이 끊어 지는지 놀라고 읽으려고 할 때만 알림을 받습니다.


답변

부끄럽지만이 문제가 발생했을 때 모든 데이터를 읽기 전에 연결을 끊은 것은 단순히 실수였습니다. 작은 문자열이 반환되는 경우 작동했지만 전체 응답이 버퍼링 되었기 때문일 수 있습니다.

더 많은 양의 텍스트가 반환되는 경우 버퍼가 더 많이 반환되므로 예외가 발생했습니다.

이 감독을 확인할 수 있습니다. URL을 여는 것은 파일과 같다는 것을 기억하십시오. 완전히 읽은 후에는 반드시 닫아야합니다 (연결 해제).


답변

전체 추적을 매우 신중하게 검사해야합니다.

서버 소켓 응용 프로그램이 있고 java.net.SocketException: Connection reset케이스를 수정했습니다 .

제 경우에는 Socket어떤 이유로 인해 연결이 닫힌 clientSocket 객체 에서 읽는 동안 발생합니다 . (네트워크 손실, 방화벽 또는 애플리케이션 충돌 또는 의도 된 종료)

실제로이 Socket 객체에서 읽는 동안 오류가 발생하면 연결을 다시 설정했습니다.

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

흥미로운 점은 for my JAVA Socket경우에 클라이언트 커넥트 내 ServerSocket닫고 아무것도 전송하지 않고 그 연결이 is.read()자신을 호출 recursively.It 때문에 무한에 닫힌 연결에서 읽으려고이 소켓에서 읽는 동안 루프가되는 것 같다. 읽기 작업을 위해 아래와 같은 것을 사용하면;

while(true)
{
  Receive();
}

그런 다음 아래와 같이 stackTrace를 얻습니다.

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

내가 한 일은 ServerSocket을 닫고 연결을 갱신하고 추가 수신 클라이언트 연결을 기다리는 것입니다.

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


//...
}

알 수없는 클라이언트 소켓 손실에 대한 연결이 다시 설정됩니다.

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...
            }
        }

아래 이미지에서 볼 수 있듯이 try and catch모든 것이 올바르게 보이기 때문에 연결이 끊어 졌는지 여부를 이해할 수 없기 때문에 다른 방법을 찾을 수 없습니다 . Connection reset계속해서 찍는 동안이 스냅 샷을 얻었습니다 .

여기에 이미지 설명 입력


답변

나는 같은 오류가 있었다. 지금 문제에 대한 해결책을 찾았습니다. 문제는 서버가 스트림을 읽기 전에 클라이언트 프로그램이 완료되었다는 것입니다.


답변

Java로 작성된 SOA 시스템에서이 문제가 발생했습니다. 나는 클라이언트와 서버를 서로 다른 물리적 컴퓨터에서 실행하고 있었고 오랫동안 잘 작동했으며 클라이언트 로그에 이러한 불쾌한 연결 재설정이 나타 났고 서버 로그에는 이상한 것이 없었습니다. 클라이언트와 서버를 모두 다시 시작해도 문제가 해결되지 않았습니다. 마지막으로 서버 측의 힙이 가득 차서 JVM에서 사용할 수있는 메모리를 늘 렸습니다. 문제가 해결되었습니다! 로그에는 OutOfMemoryError가 없었습니다. 메모리는 고갈되지 않고 부족했습니다.