본문 바로가기

JAVA/네트워크 프로그래밍

[JAVA] 서버 소켓 닫기(Server)

서버 소켓의 사용이 끝났으면 해당 소켓을 닫아야 한다. 특히 프로그램이 서버 소켓 사용 후에 바로 종료하지 않고 한동안 계속 실행되어야 할 경우 더 중요하다. 사용이 끝난 서버소켓을 닫지 않으면 다른 프로그램이 해당 포트를 사용할 수 없다.


ServerSocket을 닫는 것과 Socket을 닫는 것을 혼동해서는 안 된다. ServerSocekt을 닫으면 사용중인 로컬 호스트의 포트가 해제되며 다른 서버가 해당 포트를 바인드 할 수 있게 된다. 또한 해당 ServerSocket을 통해 수용된 모든 소켓의 연결이 끊어진다.



서버 소켓은 프로그램이 종료될 때 자동으로 닫힌다. 그래서 ServerSocket의 사용이 끝나고 곧바로 프로그램을 종료할 예정이라면 꼭 닫아야 할 필요는 없다. 하지만 종료한다고 문제가 되지는 않는다. 프로그래머들은 종종  try-finally 블록에서 "널이 아닌 경우 종료(close-if-not-null)" 패턴을 동일하게 따른다.


ServerSocket server = null;

try{

server = new ServerSocket(port);

// ..서버 소켓을 이용한 작업

} finally {

if (server != null) {

try{

server.close();

} catch(IOException ex) {

// 무시한다

}

}

}


이 코드를 예외가 발생하지 않고 실제 포트에 바인딩되지 않는 인자가 없는 ServerSocket() 생성자를 사용하여 약간 개선할 수 있다. 대신 ServerSocket() 객체가 생성된 이후에 서버 주소에 바인딩 하기 위하여 bind() 메소드를 따로 호출해야 한다.


ServerSocket server = new ServerSocket();

try{

SocketAddress address = new InetSocketAddress(port);

server.bind(address);

// ...서버 소켓을 이용한 작업

finally {

try{

server.close();

catch (IOException ex) {

// 무시한다

}

}


자바 7에서 ServerSocket은 AutoCloseable 인터페이스를 구현하고 있으므로, try-with-resources 구문을 이용할 수 있다.


try (ServerSocket server = new ServerSocket(port)) {

// ...서버 소켓을 이용한 작업

}


서버 소켓은 닫힌 후에 심지어 같은 포트라도 다시 연결할 수 없다. 즉, 한 번 닫힌 서버 소켓은 재사용할 수 없다.


isClosed() 메소드는 ServerSocket이 닫힌 경우  true를 반환하고, 그렇지 않은 경우 false를 반환한다.


public boolean isClosed()


인자 없는 ServerSocket() 생성자로 만들어졌고 아직 어느 포트에도 바인딩되지 않은 ServerSocket 객체는 닫힌 것으로 간주되지 않는다. 이 객체에 대해 isClosed() 메소드를 호출하면 false가 반환된다. isBound() 메소드는 ServerSocket 객체가 포트에 바인딩 되었는지 여부를 알려준다.


public boolean inBound()


isBound() 메소드는 ServerSocket이 포트에 바인딩된 적이 있는 경우 현재 닫혀 있더라도 true를 반환한다. ServerSocket이 현재 열려 있는지 확인이 필요한 경우 isBound()의 반환값이 true이고 isClosed()의 반환값이 false인 두 가지 조건 모두를 확인해야 한다.


public static boolean isOpen(ServerSocket ss) {

return ss.isBound() && !ss.isClosed();

}