[C# 서버에서 AS3 클라이언트 비정상 종료 체크하기]


TcpServer 에서 얻어온 client = server.AcceptTcpClient(); 

그리고

client.Client.Connected

라는 속성이 있는데 , 이것은 swf 가 종료 되었을때 체크가 불가능 하다.
그래서 예전에는 [한번 연결 , 한번 송수신 , 바로 종료] 의 매커니즘으로 안전적인 연결을 보장했다.

참고 (http://www.scripter.co.kr/entry/TCPSocket-안전한-Socket-연결과-버퍼데이터를-설정한-데이터전송-C-As3)

하지만 계속 연결을 보장해야 하는경우도 있지 않을까...

역시나 문제는 연결이 지속가능한지를 체크하여 소켓 루프를 사용가능한 상태로 만들어야 하는데 방법이 마땅치 않았다. 구지 방법을 찾자면 서로가 지속적으로 소켓을 통해

[서버 : 잘있냐? , 클라이언트 : 잘있다.] 는 연결이 건재함,
[서버 : 잘있냐? , 클라이언트 : ....] 는 연결이 손실됨 , 다시 연결 요청 

와 같이 지속적으로 물어 보는 방법이 있는데 매우 비효율적인 방법 아닌가... 참으로 서버와 클라이언트 , 둘다 득될것이 없는 방법이다.

그러던 와중 방법을 찾아 내었다.

 
while (true)
            {
                // 클라이언트 대기
                trace("wait....");
                TcpClient client;
                try
                {
                    client = server.AcceptTcpClient();
                }
                catch
                {
                    trace("ERR>> 비정상 종료");
                    return;
                }


                //환영 메세지
                byte[] sendByte = StringUTIL.StringToByte("connect Ok");
                client.GetStream().Write(sendByte, 0, sendByte.Length);
                client.GetStream().Flush();

                trace("send!");

                // client.GetStream().ReadByte()를 체크한다. 
                // 만약 연결이 유지 되고 있다면 -1 이 아닐테지만
                // swf 가 비정상 종료 , 혹은 종료 되거나 하면 -1 을 호출하여 
                // 아래의 루프를 벗어날것이다. 그리하여 소켓은 다시 사용 가능한 상태가 된다.    
                while (client.GetStream().ReadByte() != -1)
                {
                    //Console.WriteLine(c + " " + client.GetStream().ReadByte() );
                    
                    if (client.GetStream().DataAvailable)
                    {
                        NetworkStream ns = client.GetStream();
                        ns.Read(headerBuffer, 0, headerBuffer.Length);
                        string header = Encoding.ASCII.GetString(headerBuffer).Trim();
                        trace("header :" + header);

                        if (header == "close")
                        {
                            trace("cloader header!");
                            break;
                        }
                    }
                }
                trace("end!");


위의 코드 처럼 while (client.GetStream().ReadByte() != -1) 를 체크하여 루프를 돌린다면 충분히 체크가 가능하다.

물론 swf , 즉 클라이언트 프로그램이 종료 될때 close() 를 호출하여 서버에 [ 클라이언트 : 나 종료함! ~] 이라고 알려 줘야 하는게 정상이나 , swf 같은경우에는 프로그램이 종료될때 호출할수 있는 이벤트가 없다.
(하지만 AIR 는 있다.)

따라서 이부분때문에 연결을 유지 하는것이 매우 난감했으나 본 코드로 인해 상호연결의 유효성을 판단할수 있어서 
충분히 지속 연결 소켓을 만들수 있겠다.

   


하지만 위의 코드는 문제를 내포 하고 있다.
클라이언트로 받는 바이트를 1 씩 미리읽어 1바이트씩 이동 했다는것인데, 이것때문에 여럿 문제를 야기 한다.
이것의 해결책은 다음에 포스팅 하도록 한다.

그리고

if (client.GetStream().DataAvailable)
                    {

이 .. 문장도 문제가 있다.
Yamecoder 야매코더_
C# 2011.10.16 00:44

[c# TCP socket] Clinet가 죽은것을 알아채기


<TCP 서버 에서 TCP클라이언트를 이용하는 상황에서..>

TcpClient 클래스 속성중 Connected  라는 속성이 있다. 말그대로 클라이언트가 살았는지 죽었는지

판단하는 속성인데 서버에서 잘 작동하지 않는다. ( 나만 잘 모르는 것일수도 있다.)

그리고 통상적으로 while 루프 안에 스트림을 읽어 오는 코드를 작성한다음

클라이언트 프로그램이 종료 되는경우를 TcpClient 클래스 속성중 Connected  를 이용하면

무한 루프에 빠진다.

해결책은 클라이언트로 오는 바이트 수가 "0" 인것을 확인하여 처리를 해주면 된다.



             while(true)
            {
                /***중요***/
                reciveByte = new byte[1024];
            
                data = reader.ReadLine();
                if(data == null)
                {
                    Invoke(mrg , "클라이언트가 죽었습니다");
                    AceptClient();
                    break;
                }
                
                
                /*** 중요 ***/
                else if(stream.Read(reciveByte , 0 , reciveByte.Length) == 0)
                {
                    Trace.WriteLine("EXIT");
                    AceptClient();
                    break;
                }
            }
/*** 중요 ***/ 라고 되어 있는 부분을 보면 된다.

byte[] 를 하나 만들어  Stream 의 Read 속성을 적용 시켜 주면 된다.

만약 공백이라면 "1" 바이트 를, 값이 날라오지 않는 경우라면 "0"  을 반환 함으로 Client가 죽었는것을 알수 있다.

추가로 첫번째 예외처리는 서버app 를 종료할때 생기는 에러를 대처하기 위함이다.

순간적으로 data 가 Null 값이 됨으로 while 를 탈출하게 해논것이다.
 
 
 
파일 전송중 클라이언트 사망을 눈치 채기 (2012,02,12)
http://scripter.co.kr/203

Yamecoder 야매코더_
C# 2010.12.04 03:51
Powerd by Tistory, designed by criuce
rss