안녕하세요 델파이를 이제 막 시작한 초보 델피언입니다..
델피언이라고 하기에도 챙피한 수준이지만... --;
다름이 아니라 인디컴퍼넌트를 이용해서
소켓통신 플그램을 하나 만들고 있는데요.
클라이언트의 연결이 없을 때 서버소켓을 죽이는건 잘 되는데
클라이언트가 연결이 되어 있을 때
서버소켓의 active := false; 로 줬을 경우
EIdClosedSocket 과 EIdTerminateThreadTimeout 이 발생하네요.
이 예외가 발생하는것이 정상인가요?
try
serverSock.Active := false; // 여기서 위의 예외가 발생해서
blRunningServer := serverSock.Active;
updateControl;
exceptioin
//여기서 serverSock.Active 값을 보면 여전히 true 로 나옵니다.
blRunningServer := serverSock.Active;
updateControl;
end;
저렇게 종료시켰다가 다시 리스닝을 시키면 리스닝이 되지 않습니다.
쓰레드뷰어로 보니까 처음 서버프로그램 실행시켰을때
7개의 쓰레드가 생성되었다가 리스닝이 시작되면 3개의 쓰레드가 더 뜨고
클라이언트 연결시 1개의 쓰레드가 추가로 또 생성됩니다.
클라이언트가 연결된 상태에서 active:=false; 를 주면
EIdClosedSocket 예외가 발생하고
몇초동안 아무작업을 안하다가 EIdTerminateThreadTimeout 이 발생합니다.
그리고 추가로 생성되었던 4개의 쓰레드는 사라집니다.
그런데 다시 active:= true; 로 주면 생성되어야 할 3개의 쓰레드가
생성이 안되는군요.. 아마도 서버소켓의 active 가 아직 true 의 상태여서
그런게 아닐까 생각해보는데요..생성되어야 할게 안됬으니
리스닝을 못하는건 당연하지요.죽였다 살리는 작업을 한번 더 하면
그때부턴 다시 리스닝이 됩니다.
그리고 netstat -na 로 보니까 예외가 발생하면서 종료되었던
연결은 Time_wait 상태로 계속 나오네요.
정상적으로 클라이언트에서 연결단절 시킨건 사라지는데
서버를 강제로 active:=false; 했을 경우에는 time_wait 상태로 계속 있습니다.
위에 발생하는 저 예외가 정상적으로 나오는 건지 아니면
제가 뭔가 중요한 실수를 해서 나오는건지 알 수가 없어서
이렇게 글을 올립니다.
그리고 인디소켓이 내부적으로 쓰레드를 사용하는거 같은데
소켓을 종료한다거나 할 때 별도의 쓰레드 해제 작업같은건
안해도 되는지요.예를 들어 클라이언트 접속 종료시
onDisconnect 이벤트에서 AThread.Terminate; 를 해줘야 한다던지....
저 위의 상황 말고도 인디소켓을 이용할 경우 자칫 지나칠 수 있는
중요한 사항이 있으면 덧붙여서 설명해주시면 너무너무 감사하겠습니다.
그럼 복들 많이 받으세요~~
>델피언이라고 하기에도 챙피한 수준이지만... --;
>
>다름이 아니라 인디컴퍼넌트를 이용해서
>소켓통신 플그램을 하나 만들고 있는데요.
>
>클라이언트의 연결이 없을 때 서버소켓을 죽이는건 잘 되는데
>클라이언트가 연결이 되어 있을 때
>서버소켓의 active := false; 로 줬을 경우
>EIdClosedSocket 과 EIdTerminateThreadTimeout 이 발생하네요.
>
>이 예외가 발생하는것이 정상인가요?
>
==> 정상적인 예외입니다... Indy는 에러 메카니즘을 Exception을 사용합니다.
>try
> serverSock.Active := false; // 여기서 위의 예외가 발생해서
> blRunningServer := serverSock.Active;
> updateControl;
>exceptioin
> //여기서 serverSock.Active 값을 보면 여전히 true 로 나옵니다.
> blRunningServer := serverSock.Active;
> updateControl;
>end;
>
>저렇게 종료시켰다가 다시 리스닝을 시키면 리스닝이 되지 않습니다.
>쓰레드뷰어로 보니까 처음 서버프로그램 실행시켰을때
>7개의 쓰레드가 생성되었다가 리스닝이 시작되면 3개의 쓰레드가 더 뜨고
>클라이언트 연결시 1개의 쓰레드가 추가로 또 생성됩니다.
>
>클라이언트가 연결된 상태에서 active:=false; 를 주면
>EIdClosedSocket 예외가 발생하고
>몇초동안 아무작업을 안하다가 EIdTerminateThreadTimeout 이 발생합니다.
>그리고 추가로 생성되었던 4개의 쓰레드는 사라집니다.
>
>그런데 다시 active:= true; 로 주면 생성되어야 할 3개의 쓰레드가
>생성이 안되는군요.. 아마도 서버소켓의 active 가 아직 true 의 상태여서
>그런게 아닐까 생각해보는데요..생성되어야 할게 안됬으니
>리스닝을 못하는건 당연하지요.죽였다 살리는 작업을 한번 더 하면
>그때부턴 다시 리스닝이 됩니다.
>
==> 맞습니다. 한번 False로 셋팅하시면, 기존의 연결들을 해제하면서 EIdClosedSocket Exception이 발생하고요, ThreadPool에서 Listening Thread를 죽이면서 설정된 TimeOut(기본 5초)을 기다렸다가 아무 응답이 없으면 EIdTerminateThreadTimeOut을 발생합니다.
Exception과 Error를 착각하시면 않됩니다. Exception이 곧 Error가 아니구요.. Exception중에서 Error가 있을 수 있습니다.. Error가 더 큰범위이지요.. Indy도 보면, Connection Closed Gracefully 를 사용합니다. 종료할때의 Exception이지요.. 클라이언트가 서버에서 disconnect할 때는 두가지 방식이 있습니다. Mutual Agreement와 Single Disconnect이죠.. 요 링크로 가셔서 읽어 보세요. Indy의 Author가 적은 기사입니다.
>그리고 netstat -na 로 보니까 예외가 발생하면서 종료되었던
>연결은 Time_wait 상태로 계속 나오네요.
>정상적으로 클라이언트에서 연결단절 시킨건 사라지는데
>서버를 강제로 active:=false; 했을 경우에는 time_wait 상태로 계속 있습니다.
>
>위에 발생하는 저 예외가 정상적으로 나오는 건지 아니면
>제가 뭔가 중요한 실수를 해서 나오는건지 알 수가 없어서
>이렇게 글을 올립니다.
>
==> 실수가 아닙니다. 정상적으로 발생하는 예외입니다.
>그리고 인디소켓이 내부적으로 쓰레드를 사용하는거 같은데
>소켓을 종료한다거나 할 때 별도의 쓰레드 해제 작업같은건
>안해도 되는지요.예를 들어 클라이언트 접속 종료시
>onDisconnect 이벤트에서 AThread.Terminate; 를 해줘야 한다던지....
>
==> 그렇지 않습니다. 쓰레드는 전적으로 서버콤포넌트에서 알아서 해줍니다.
>저 위의 상황 말고도 인디소켓을 이용할 경우 자칫 지나칠 수 있는
>중요한 사항이 있으면 덧붙여서 설명해주시면 너무너무 감사하겠습니다.
>
>그럼 복들 많이 받으세요~~