2010-06-06 2 views
117

내 주 스레드에서 내 ServerSocket 개체에 accept()을 호출 한 while(listening) 루프가 있고 새 클라이언트 스레드가 시작되고 새 클라이언트가 받아 들여지면 컬렉션에 추가됩니다.ServerSocket accept() 메소드를 중단하려면 어떻게해야합니까?

'exit'와 같은 명령을 실행하는 데 사용하고자하는 Admin 스레드도 있습니다.이 스레드는 모든 클라이언트 스레드를 종료하고 자체 종료하고 주 스레드를 종료하는 원인이됩니다. 거짓으로.

그러나 accept() 루프 블록은 while(listening) 루프 블록을 호출하며 중단 할 수있는 방법이없는 것 같습니다. 따라서 while 조건을 다시 검사 할 수없고 프로그램을 종료 할 수 없습니다!

더 좋은 방법이 있나요? 또는 차단 방법을 방해하는 어떤 방법?

+1

참조하십시오. http://stackoverflow.com/questions/2804797/java-stop-server-thread – CuriousPanda

답변

119

당신은 다른 스레드에서 close()를 호출 할 수 있으며, accept() 호출은 SocketException 발생합니다. 동의에

+1

감사합니다. 너무 분명해서 나에게 발생하지 않았습니다! 루프를 종료 한 후 close()를 호출했습니다. – lukeo05

+4

이상한 점은 docs에이 정보가 없다는 것입니다. http://download.oracle.com/javase/6/docs/api/java/net/ServerSocket.html#accept%28%29 메서드가 SocketException을 던지는 것으로 표시되지 않았습니다. . 여기에 언급되어 있습니다. http://download.oracle.com/javase/1.4.2/docs/api/java/net/ServerSocket.html#close%28%29 –

+1

'close()'를 호출해도 괜찮습니까? 나는 그것을 수행하는 예외를 던질거야, 그래서 다른 방법 (예외를 throw하지 않는, 또한 타임 아웃을 기반으로하지 않는) 요청을 듣고 중지하는거야? – Kushal

24

설정 시간 제한(), 다음 호출은 지정된 시간 후 차단 시간 초과됩니다

http://docs.oracle.com/javase/7/docs/api/java/net/SocketOptions.html#SO_TIMEOUT

는 소켓 조작의 블록에 타임 아웃을 설정 : ServerSocket.accept를(); SocketInputStream.read(); DatagramSocket.receive();

옵션을 적용하려면 차단 작업을 시작하기 전에 설정해야합니다. 타임 아웃이 끝났고 조작이 계속 차단되면 java.io.InterruptedIOException이 발생합니다. 소켓은이 경우 닫히지 않습니다.

0

클리너를 시도해 볼 수있는 또 다른 방법은 accept 루프에서 플래그를 확인한 다음 관리 스레드가 accept에서 블로킹을 중단하고 플래그를 설정하여 스레드를 안전하게 설정하는 것입니다. 청취 소켓에 대한 클라이언트 소켓 연결을 만듭니다. accept는 블로킹을 중지하고 새 소켓을 반환합니다. 청취 스레드가 정상적으로 스레드를 종료하도록 알려주는 간단한 프로토콜을 구현할 수 있습니다. 그런 다음 클라이언트 측 소켓을 닫습니다. 예외가 없으므로 훨씬 더 깨끗합니다. 당신이 의 OutputStream을하거나 소켓에 부착되는 InputStream 때문에

3

serversocket.close()예외을 발생하는 이유입니다. 먼저 입출력 스트림을 먼저 닫음으로써이 예외를 안전하게 피할 수 있습니다. serversocket을 닫으십시오. 간단한 방법

void closeServer() throws IOException { 
    try { 
    if(outputstream!=null) 
     outputstream.close(); 
    if(inputstream!=null) 
     inputstream.close(); 
    } catch (IOException e1) { 
    e1.printStackTrace(); 
    } 
    if(!serversock.isClosed()) 
    serversock.close(); 
    } 
} 

단순히 처리 할 수있는 예외를받지 않고 어느 곳에서이 메소드를 호출하여 모든 소켓을 닫을 수 있습니다을 작성합니다.

+4

입력 스트림과 출력 스트림은'ServerSocket'에 붙어 있지 않고'Socket'에 붙어 있습니다.'Socket'이 아니라'ServerSocket'을 닫으려는 것이므로'Socket'을 닫지 않고'ServerSocket'을 닫을 수 있습니다 님의 개울. – icza

3
당신은 단지 휴식 serversocket.accept()

서버 측 "무효"소켓을 만들 수 있습니다

private static final byte END_WAITING = 66; 
private static final byte CONNECT_REQUEST = 1; 

while (true) { 
     Socket clientSock = serverSocket.accept(); 
     int code = clientSock.getInputStream().read(); 
     if (code == END_WAITING 
      /*&& clientSock.getInetAddress().getHostAddress().equals(myIp)*/) { 
      // End waiting clients code detected 
      break; 
     } else if (code == CONNECT_REQUEST) { // other action 
      // ... 
     } 
    } 

휴식 서버주기위한 방법

void acceptClients() { 
    try { 
      Socket s = new Socket(myIp, PORT); 
      s.getOutputStream().write(END_WAITING); 
      s.getOutputStream().flush(); 
      s.close(); 
    } catch (IOException e) { 
    } 
} 
관련 문제