Socket의 종료( closesocket )
Posted 2012. 10. 16. 15:13소켓의 종료는 closesocket함수를 호출하면 종료 하게 된다.
하지만 단순히 closesocket만 호출하면 문제가 발생 할 수 있다.
그 문제가.. 온라인게임을 서비스 하는 입장이라면 단순하지 못한 문제..
closesocket를 호출 했을때 어떻게 종료가 되는지 흐름을 알아야 한다.
1. A가 B에게 연결 종료를 요청한다
2. B는 종료전 할 일이 남아있기 때문에 FIN를 보내지않고 ACK만 보내고 CLOSE_WAIT 상태로 넘어간다.
-> 할 일이란. 송(수)신버퍼상 남아있는 데이터를 모두 전송하는 작업임
3. 작업이 끝난 후 B는 FIN를 보내고 연결을 종료하고자 한다.
4. A는 B의 FIN을 잘 받았다는 ACK를 B에게 보내게 되고 A의 ACK를 받으면 B는 종료한다.
문제는 4번 과정에서 A는 ACK를 보내고 소켓이 제거될때까지 TIME_WAIT라는 상태에 있게 되는데
(약 4분)이 TIME_WAIT에 빠지는 이유는 A가 B로 보낸 마지막 종료 메세지 이후 바로 종료하면
라우터나 기타네트워크 상에서 발생하는 문제들에 의해 마지막 종료 메세지가 B에 도착 하지 못했을때
생긴다. 그러면 B는 종료하지 못하고 다시 A에게 마지막 FIN을 보내게 된다.
여기서 A가 TIME_WAIT가 아니라 강제종료된 상태라면 이 마지막 FIN역시 무시됬을테고 B는 여전히
A가 어떤상태인지 모르고 대기하게 된다.표준대기시간인 4분동안...
이게 무슨 문제냐면.. TCP규정상 TIME_WAIT상태일때 그 포트를 다른 프로세서가 이용하지 못하게
막아 두었다. 그래서 해당 소켓을 사용 하지 못하게 된다.
사용할수 있는 포트가 65535개나 되고 일정시간(약4분)이 지나면 사용 할 수 있게 되는데
이게 무슨 문제가 되겠냐.. 하면
로그인을 처리하는 로그인서버를 보면..
유저가 100만명인 게임이 잘 돌아가다가 예기치 못하게 서버 다운이 되었을 경우
서버를 재가동할때 100만명의 유저가 한번에 몰리게 된다.
이런경우 4분만에 포트를 다 소비하지 않는다고 장담 할 수가 없다..
이 같은 경우도 생각 해 두어야한다.
이럴때를 대비해 socket옵션에서 SO_LINGER를 사용해 대기없이 바로 종료하게 하면 된다.
간단히 끝날 문제를 대비해두자. 그냥 넘어갈 이유는 없다.
- Filed under : Server/Socket의 종료