Non-Blocking 소켓 연결후 연결끊김(connection lost)을 알아내는 방법?
Non-blocking 모드로 서버에 연결하는 코드를 작성중입니다.
UnicastOpen(), UnicastRecv() 등과 같이 Wrapper 형태로 작성을 하고 있습니다.
UnicastOpen을 non-blocking 모드로 구현하면 대략 아래와 같은 절차가 됩니다.
non-blocking 모드 설정 -> connect() -> errno EINPROGRESS 체크
-> select() -> getsockopt () 체크
UnicastRecv()는 간단하게 아래와 같이 구현하려 합니다.
connection 상태 체크 -> select() -> recv()
즉, connection이 끊기지 않은 상태인지 UnicastRecv()에서 한 번 체크해야 하는 상태입니다.
그냥 뒤에 이어져서 나오는 recv()의 결과에 따라 처리할 수도 있겠지만, 사양상 UnicastRecv()
함수 역시 blocking이 되면 안 되기 때문에 별도의 쓰레드 상에서 구현하다 보니 recv()의 결과를 이용하기는 힘듭니다.
UnicastOpen() 함수에서는 connect의 리턴값과 errno, sockopt 값을 체크해서 connect 시도가 성공적인지
제대로 체크가 된다고 보구요.
UnicastOpen() 함수가 제대로 실행되었지만, UnicastRecv() 실행 이전에
connection이 끊기는 경우를 탐지해야 하는데, 이를 어떻게 할지가 조금 난감하네요.
구글 검색을 통해 getpeername()이나 read(fd, &ch, 0)를 사용해보았지만 제대로 동작하지 않습니다.
UnicastOpen() 실행 이후에 네트워크 cable을 뽑아놓았음에도 불구하고, 두 경우 모두 0을 return하는
걸 보니 connection이 끊긴 것을 알아차리지 못하는 모양입니다.
connect를 2번 해보는 것도 한 방법인 것 같은데, 이 방법이 유일하게 남은 것일까요?
좀 더 깔끔한 방법을 아시는 분 계시면 알려주시면 감사하겠습니다.
그런것을 감지하려면 얘기가 좀 다른걸로 알고있습니다.
일단 실제로 케이블을 뽑는것이라면 온라인 여부만 체크하는 것을 따로 돌리면 되겠지만 그것은 아니실테고
정상적으로 close하는것이 아닌, 통신주체가 다운되는등의 이유로 연결이 죽었을때를 감지하려는 것으로 이해했습니다.
근데 해보셔서 아시겠지만 이게 쉬운일이 아닙니다.
SO_KEEPALIVE_VALS를 이용할 수 있으나 이것도 연결종료를 그즉시 감지해낼수는 없으며 그나마도 모든 플랫폼에서 다 지원하는 것도 아니라고 알고있습니다.
결국 직접 킵얼라이브 패킷을 주고받아야 되는걸로 알고있는데요. 이렇게 되면 상대방이 다운되더라도 그 킵얼라이브 주기동안은 알아낼수가 없는거지요..
제가 문제를 제대로 이해했는지는 모르겠으나,
안전하게 하시려면 수동으로 데이터를 교환하는 방식으로 해결을 보심이 어떨까 합니다.
커넥션을 두 번 한다는게 어떤 의미인지는 모르나 하여튼 자동으로 해주는것은 없다 생각하고 말씀하신 류의 별도의 방법을 써보시는게 좋겠다는 얘기죠.
--
This is for you new people. I have just one rule :
Everyone fights, no one quits. If you don't do your job, I'll shoot you myself. Do you get me?
--
답변 감사드립니다.
답변 감사드립니다.
사양서대로 구현을 하고 있는 중인데, "connection lost"인 상태에서 UnicastRecv() 함수를
호출하면, 따로 정의된 Error Code를 return해주어야 하거든요.
저는 케이블을 뽑아서 테스트했던 건데, server가 죽는 경우일 수도 있을 것 같고, 좀 애매하긴 하네요.
KEEPALIVE도 들어보긴 했는데, 주기를 설정하자니 한없이 작게 하기도 그렇고 명확한 솔루션이 될지 의문이 있네요.
답변 말씀 참조하도록 하겠습니다~
댓글 달기