[C#] 소켓통신간 클라이언트 끊어짐 감지

Jaemoon Lee·2022년 11월 11일
0

[C샾]

목록 보기
6/13

프로그램 개발 중...
내 프로그램(서버)에 연결된 타 클라이언트 프로그램의 예상치 못한 종료를 감지하지 못하는 현상을 제보 받았다.

클라이언트의 예상치 못한 종료란
PC의 재부팅, 랜 케이블의 물리적으로 차단, 클라이언트 프로그램이 버그로 인해 종료..
등을 예로 들 수 있는데

테스트결과 이런 상황에 클라이언트 프로그램을 다시 켠 뒤 통신 Connect를 하면 기능상 이상은 없는 것으로 확인 되었다.
(아마 서버가 클라이언트의 접속 요청 Accept를 판단하는 과정에서 포트를 사용중인 누군가가 있는지 체크한 뒤 비어있으면 Accept를 해주는 과정을 거치기 때문에 그런게 아닐까.. 하고 추측해본다.)

또한 프로그램 자체적으로.. 클라이언트나 서버와 주고받는 메시지 중 Recv 구간에 타임아웃을 넣어놨기 때문에... 사용하는데 이상은 없는 것으로 판명났으나... UI상이나 추후 어떤 문제가 발생할지 모르기 때문에 해당 현상을 수정하기로 결정하였다.

아무튼 서론이 길었는데...
가장 확실한 방법은 서버↔클라이언트간 주기적으로 Alive를 알리는 통신 프로토콜(이것을 Heart Beat 통신 이라고 칭한다.)을 지정하고,
상호간 일정 시간동안 Alive 메시지가 Recv 되지 않으면 소켓을 Close 하는 것이다.

하지만 이제 와서 프로토콜을 다시 정하여 클라이언트들에게 배포해 프로그램을 수정하라고 할 수도 없는 노릇이므로...
서버 프로그램 수정만으로 소켓 통신 Connect를 감시할 수 있는 기능을 만들어보았다.

public bool IsSocketConnected()
{
	return isClientConnect;
}

↑ 기존의 소켓 통신 연결 상태를 알려주는 IsSocketConnected 함수의 경우 프로그램 실행 시 소켓이 수동적으로 끊어지지 않는 한 1번의 boolean 변수 isClientConnect를 반환하였다.

public bool IsSocketConnected()
{
try
	{
		return !(Handler.Poll(1, SelectMode.SelectRead) && Handler.Available == 0);
	}
	catch (SocketException)
	{
		return false;
	}
	catch (Exception)
	{
		return false;
	}
}
while (Store.getInstance().runningLoops)
{
	if (!Store.getInstance().server.IsSocketConnected() && Store.getInstance().ClientDisconnectFlag)
	{
	//연결 끊김 감지
	//UI변경
	Store.getInstance().twLog.WriteLog("[서버] : 검사기 끊김");
	Store.getInstance().ClientDisconnectFlag = false;
    
    //이하 아래 코드들 계속....

↑ 그러나 실시간으로 소켓 통신 연결 상태를 알려주기 위해서는 해당 함수를 반복적으로 돌려 소켓 통신 상태를 확인해야 했고,
C# Socket 클래스에서 제공하는 Poll과 Available 기능을 사용하였다.

  1. try → Poll(소켓 현재 상태)와 Available(소켓 데이터 읽을 수 있는 상태) 감시
  2. catch → Poll과 Available이 SocketException, Exception 될 경우, 소켓 통신이 닫히거나 끊어진 상태임을 의미하므로 IsSocketConnected()가 false를 반환.
  3. 아래로 넘어와, runningLoops(소켓 통신 지속 쓰레드)가 지속되는 동안 IsSocketConnected()를 반복(while)한다.
  4. IsSocketConnected()가 false를 반환하고 + ClientDisconnectFlag(소켓 끊어짐 플래그)가 true면 아래 연결 끊어짐을 알리는 UI 변경이나 로그를 출력한다.

이외에 회사에서 받은 소켓 통신 테스트용 프로그램은
조금 다른 방식으로 실시간 소켓 통신 연결 감시를 구현했던데...
이해가 완료되면 간단하게 다뤄보도록 하겠다.

참고 ↓↓↓↓↓

Socket.Poll에 대한 자세한 정보
https://learn.microsoft.com/ko-kr/dotnet/api/system.net.sockets.socket.poll?view=net-7.0

Socket.Available에 대한 자세한 정보
https://learn.microsoft.com/ko-kr/dotnet/api/system.net.sockets.socket.available?view=net-7.0

profile
초보개발세발자

0개의 댓글