ProgramingTip

Java 소켓 API : 연결이 닫혔는지 확인하는 방법은 무엇입니까?

bestdevel 2020. 10. 7. 07:57
반응형

Java 소켓 API : 연결이 닫혔는지 확인하는 방법은 무엇입니까?


Java 소켓 API에 몇 가지 문제가 있습니다. 현재 내 게임에 플레이어 수를 표시합니다. 확인할 수 있습니다. 그러나 소켓 소켓 API를 사용하여 확인의 연결이 더러워진시기를 확인하는 것은 추측하게 어려워집니다.

isConnected()원격으로 연결이 끊어진 소켓에 대한 호출 은 항상 반환되는 시청 true. 거의 isClosed()원격으로 소켓을 호출 하면 항상 false. 소켓이 닫혔는지 여부를 확인하기 위해 데이터를 출력 스트림에 기록하고 있다는 것을 입증했습니다. 이것은 상황을 처리하는 정말 불결한 방법 인 것입니다. 우리는 소켓이 언제 닫혔는지 알기 위해 네트워크를 통해 쓰레기 메시지를 발송해야합니다.

다른 서열이 있습니까?


현재 연결 상태를 알려주는 TCP API는 없습니다. isConnected()그리고 isClosed()당신에게 현재 상태에게 당신의 소켓을 . 같은 것이 아닙니다.

  1. isConnected()이 소켓 을 연결 했는지 여부 알려줍니다 . 그래서 그것은 사실을 반환합니다.

  2. isClosed()이 소켓 을 닫았 는지 여부 알려줍니다 . 당신이 유일한 경우에만 그렇게하지 않습니다.

  3. 피어순서대로 연결닫은 경우

    • read() -1 반환
    • readLine() 보고 null
    • readXXX()EOFException다른 XXX에 대해 던졌습니다 .

    • 쓰기는 IOException결국 버퍼링 지연에 따라 '피어에 의해 연결되는' 을 던집니다 .

  4. 다른 뮤직 연결이 더러워진 경우 쓰기는 IOException결국 위와 같이를 던져 하고 읽기는 동일한 작업을 수행 할 수 있습니다.

  5. 피어가 여전히 연결되어있을 경우 사용하지 않는 경우에는 사용할 수 없습니다.

  6. 다른 곳에서 읽을 수있는 ClosedChannelException것과 동일한 것입니다. [도 안함 SocketException: socket closed.] -channel 닫은 다음 계속 사용 했음을 알려줍니다 . 즉, 귀하의 프로그래밍 오류입니다. 닫힌 연결을 사용 할지 .

  7. Windows XP에서 Java 7을 경우 몇 가지 실험 결과 다음과 같은 경우에도 나타납니다.

    • 당신은 선택하고 있습니다 OP_READ
    • select() 0보다 큰 값을 반환합니다.
    • 항목 연결된 SelectionKey이 이미 잘못되었습니다 ( key.isValid() == false).

    피어가 연결을 사용했음을 의미합니다. 그러나 이것은 JRE 버전 또는 플랫폼에 고유 할 수 있습니다.


다양한 메시징 프로토콜에서 서로 하트 비트를 유지하는 것이 일반적입니다 (핑 패킷을 계속 전송). 패킷이 매우 클 필요는 없습니다. TCP가 일반적으로 사용하기 전에 연결이 더 많은 클라이언트를 감지 할 수 있습니다 (TCP 시간 초과가 훨씬 더 높음). 5 초 동안 보내는 응답을 위해. 계속해서, 플레이어의 연결이 더 끔찍합니다.

또한 관련 질문


게시 된 다른 답변을 보지만 게임을하는 클라이언트와 상호 작용할 생각을 다른 접근 방식을 사용할 수 있습니다 (BufferedReader는 어떤 경우에는 확실히 유효합니다).

"등록"책임을 클라이언트에게 위임 할 수 있습니다. 즉, 각각에서받은 마지막 메시지에 타임 스탬프가있는 사용자 모음이있을 것입니다. 클라이언트가 시간 초과하면 클라이언트를 강제로 다시 등록해야하지만 아래의 인용문과 아이디어로 이어집니다.

소켓이 닫혔는지 여부를 실제로 확인하기 위해 데이터를 출력 스트림에 기록해야하고 예외를 잡아야한다는 것을 읽었습니다. 이것은 상황을 처리하는 정말 불결한 방법 인 것입니다.

Java 코드가 소켓을 닫거나 연결 해제하지 않은 경우 원격 호스트가 연결을 닫았다는 알림을 어떻게받을 수 있습니까? 즉, try / catch는 ACTUAL 소켓에서 이벤트를 수신하는 폴러가 수행하는 것과 거의 동일한 작업을 수행합니다. 다음을 고려하세요 :

  • 로컬 시스템은 사용자에게 알리지 소켓을 닫을 수 있습니다. 이것은 소켓의 구현 일뿐입니다 (즉, 변경을 위해 하드웨어 / 드라이버 / 상태 펌웨어 / 무엇이든 폴링하지).
  • 새 소켓 (Proxy p) ... 여러 끝점 (실제로는 6 개의 개의 연결을 사용할 수 있습니다 ...

추상화 된 언어의 특징 중 하나는 당신이 사소한 부분에서 예시는 것입니다. SqlConnection에 대한 C # (try / finally)의 키워드를 사용해 생각해 ... 그것은 단지 비즈니스를 수행하는 비용 일뿐입니다. try / catch / finally는 소켓 사용을위한 허용되고 필요한 패턴이라고 생각합니다.


저는 이것이 TCP 연결의 특성이라고 생각합니다. 표준에서 송신 연결이 끊어 졌다고 결론을 내리기까지 약 6 분 동안 무음으로 전송됩니다! 따라서 이러한 문제에 대한 해결책을 알 수 있습니다. 아마도 더 나은 방법은 서버가 사용자 연결이 닫혀 있다고 가정해야하는 추측하는 편리한 코드를 작성하는 것입니다.


@ user207421이 말했듯이 TCP / IP 프로토콜 아키텍처 모델로 인해 현재 연결 상태를 알 수있는 방법이 없습니다. 따라서 서버는 연결을 닫기 전에 사용자를 인식해야하거나 사용자가 직접 확인해야합니다.
다음은 서버가 소켓을 닫는 방법을 간단하게 예입니다.

sockAdr = new InetSocketAddress(SERVER_HOSTNAME, SERVER_PORT);
socket = new Socket();
timeout = 5000;
socket.connect(sockAdr, timeout);
reader = new BufferedReader(new InputStreamReader(socket.getInputStream());
while ((data = reader.readLine())!=null) 
      log.e(TAG, "received -> " + data);
log.e(TAG, "Socket closed !");

그게 내가 처리하는 방법

 while(true) {
        if((receiveMessage = receiveRead.readLine()) != null ) {  

        System.out.println("first message same :"+receiveMessage);
        System.out.println(receiveMessage);      

        }
        else if(receiveRead.readLine()==null)
        {

        System.out.println("Client has disconected: "+sock.isClosed()); 
        System.exit(1);
         }    } 

result.code == null 인 경우


리눅스에서, 당신이 모르는 다른 쪽이 닫혀있는 소켓에 write () ing을하면 SIGPIPE 신호 / 예외가 발생하지만 당신이 그것을 호출하고 싶을 것입니다. 그러나 SIGPIPE에 걸리지 않으려면 MSG_NOSIGNAL 플래그와 함께 send ()를 사용할 수 있습니다. send () 호출은 -1로 반환되며이 경우에는 errno.h에 따라 다음과 같은 값 EPIPE로 끊어진 파이프 (이 경우 소켓)를 작성하려고 시도했음을 알려주는 errno를 확인할 수 있습니다. 32. EPIPE에 대한 반응으로 두 배로 돌아가 소켓을 다시 열고 정보를 다시 보내려고 할 수 있습니다.


먼저 소켓이 현재 NULL인지 아닌지 확인한 다음 닫히지 않았는지 확인합니다.

if(socket!=null && !socket.isClosed()){
//good to go
}

참고 URL : https://stackoverflow.com/questions/10240694/java-socket-api-how-to-tell-if-a-connection-has-been-closed

반응형