C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 팁&트릭
C++Builder Programming Tip&Tricks
[1159] 가상 PLC, IdUDPServer UDP 수신 종료시 먹통 해결방법
박영목.월천 [gsbsoft] 8154 읽음    2015-01-31 18:30
VirtualPLC.zip 280.4KB 실행, 소스파일
가상 PLC, IdUDPServer UDP 수신 종료시 먹통 해결방법


C++Builder 6.0,  INDY 9.0.18


저는 UDP를 그냥 소켓 생성해서... 나름대로 좀 안전하게 한다고...

INDY 사용하지 않았는데...

PLC쪽 프로그램을 해주다 보니... PLC를 늘 가지고 다닐 수도 없고

그래서 아주 간단히 그냥 값만 보려고... 만들었습니다.

헐 그런데 IdUDPServer UDP 수신하다 disconnect하면  먹통....

그래도 그렇게 값을 많이 보는 것도 아니고 잠시 잠시 보는 것이라

그냥 종료하고 다시 실행하고... 이런씩으로 했는데....

오늘 이 INDY 함 잡아보자는 생각에....   검색도 하고 연구도 하고

해서 알아내었습니다. 짝짝짝....   별것 아닌데....ㅠㅠ

그리고 혹 PLC 작업하는 분들을 위해 간단하지만 제가 사용하는

간단한 가상 PLC UDP 수신 프로그램 올려드리니 많은 사용바랍니다.

-------------------------------------------------------------------------

올리고 나서... 한번 더 Test 하는 데...  너무 불친절한 프로그램이라는 것을 알았습니다.

어떤 PLC인지도 없고 PORT 바꾸는 데도 없고... ㅋㅋㅋ  제가 그냥 사용하던 것이라...

그래서 좀 수정해서...  LS PLC, SIMON PLC UDP 2개 바꾸어 사용할 수 있도록 추가했습니다.

(아~~ 가만 생각하니... 밑에 이진수 출력은 SIMON에 맞추어져 있을 것 같습니다. 원래 이진수 출력
없다가 요근래 붙혔는데.... SIMON과 LS의 HEAD 부분의 길이가 다를 것 같은 데.... 생각안남...  이진수 출력은
24Byte 부터 되어 있을 것인데....  조금 수정해서 사용하십시오.... 죄송...)

한번 더 Test해 보니 이 프로그램에서 수신시작 , 수신종료는 이제 잘 되는데...  먹통도 되지 않고
Client에서 가상 PLC에 보냈다가 끊었다가 하면 Data가 들어오지 않는 문제가 있네요...
그럭저럭 쓸만한 프로그램 만들려고 하니  이렇게 간단한 것도... 손이 많이 가네요...

Client는 일반소켓으로 만들었는데... 혹 TIdUDPClient로 만들면 접속이 끊기면
TIdUDPServer에서 감지해서 Bindings를 Clear할까?  그래도 문제가 발생할 것 같은 데....
Client가 갑자기 죽으면 자기가 나간다는 것을 알릴 수 없을 것이므로...

IdUDPServer1->ReceiveTimeout = 5000;
이것은 5초 동안 Data가 안들어 오면 Binding을 해제하는 것이 아닌가?
대체 이 놈은 뭐야...   이것 뭐 Indy를 자주 사용하지 않으니...

UDP가 TCP처럼 계속 연결되어 있는 것이 아니기 때문에... 접속이 끊겨도(이 말도 웃기지만, 지속연결방법이 아니므로)
Server가 끊긴 것을 모르는 것이 맞는데.... 끙끙....

Client가 Disconnect 되면 바로 감지하는 TCP처럼 매끄럽게 처리하려면 Client, Server 간의
프로토코을 잘 정의해서 작성해야 할 것 같다....  하기 싫음...

그리고 현제 UDP에서 나의 작업은 장비와 통신 밖에 없는데 프로토콜을 잘 정의할 것도 없을 것 같고...
간단히 PLC로 전달되는 가상값을 보고 싶을 뿐이므로....
그냥 일정시간마다... 서버를 죽이고 Bindings를 Clear하고 다시 살리고를 1초 동안 계속
하려고 한다.  이 부분을 쓰레드로 만들면  TForm1::IdUDPServer1UDPRead와 문제가 혹 발생할 것 느낌이(충돌)....
그냥 Timer로 하는 것이 안전해 보인다.  그래서 Timer 하나 붙이고...
2초 해도 충분하겠는데...  Data를 많이 보내는 것도 아니고 해서.... 그냥 1초로 해서  Bindings를
계속 Clear하게 만들어 버렸습니다......

이제 잘 되는군...  Client가 Reconnect해도 먹통없이 잘 수행합니다......  



void __fastcall TForm1::IdUDPServer1UDPRead(TObject *Sender,
      TStream *AData, TIdSocketHandle *ABinding)

{

  //이곳에 Application->ProcessMessages();
  //이 Code 들어 있으면 먹통됩니다.

  //이런 곳에 위의 것을 넣으면 프로그램 멈춤니다. 위의 이것이 델파이나 빌더에서
  //예제해서도 종종 보입니다. 그러므로 적절한 곳에 사용하는 것은 맞는데...
  //어떤 때는 꼭 사용해야 기름을 친듯 잘 돌아갑니다.
  //( 프로그램이 점점 커지고 기능이 많다보면 뭔가 잘 안돌 때 한번씩 사용합니다 물론 Sleep()과 쌍으로...)

  //그런데 이것을 오용하면 이 프로그램에서 처럼 죽습니다.

  //----------------------------------------------------------------------------

}



접속 끊을 때는 이렇게....

void __fastcall TForm1::BtnStopRecvClick(TObject *Sender)
{
    IdUDPServer1->Active = false;

    //실험해보니 아래것 말고 IdUDPServer1->Bindings->Clear(); 이것을 사용해도 잘 되는 군요...

    int i=0;
    while( i<IdUDPServer1->Bindings->Count )
    {
      IdUDPServer1->Bindings->Items[i]->Free();      //<---  핵심은 이 부분......
      i++;
    }
}

망치 [mangchy]   2015-02-01 19:00 X
요즘 저도 개발하고 있는 프로그램에 PLC들 추가하고 있는데 마침 잘 되었네요...
감사합니다.
박영목.월천 [gsbsoft]   2015-02-03 20:25 X
망치님 새해 복 많이 받으세요^^ 
올해는 경기가 좀 살아나려나...  정치.... 투표... 생각해봅니다...  사실 고차원적이고 남을 배려하는 평범한 사람들, 우리들은 별로 정치에 관심이 없습니다. 그리고 사실 투표할 때 찍을 사람도 없고... 그래서 투표는 덜 나쁜 놈을 뽑는 것이다라는 말도 있고... 현제 정권이 못하면 무조건 다음 투표 때 다른 당을 찍는다... 그런데 당이 두개가 아니라서 서로 다른 당을 찍으면 또 집권당이 승리할 것이고... 이래도 저래도 문제.... 당이 딱 2개라면 아주 우리 뜻대로 이랬다 저랬다 갖고 놀 것인데...  오늘 아내에게 들은 이야기...  어느 초등학교 반장 투표를 했는데 그 반에서 제일 모자라는 학생이 반장으로 뽑혔다고 합니다. 이유는 잘난체 하는 애들 뽑으면 자기들만 피곤하다고...  요즘 아이들 정말 똑똑합니다. 우리 때는 상상하지도 못할 일,,,  갑자기 이숍우화 "왕을 원한 개구리들"이 생각나는 군요... 아무 일도 하지 않는 통나무왕이 좋았다는 것....   반에서 제일 멍청한 나같은 아이를 반장으로 뽑은 우리들의 아이들이 있기에 우리 나라의 미래는 그렇게 어둡다고 생각안합니다.  언제가 이런 아이들이 투표하는 날... 우리가 생각해 내지 못한 지혜로 이 나라를 구해줄지...  아이들 많이 낳아야 하는데...  개구리 왕국처럼 황새에게 다잡아 먹혀 버리지 않고 끝까지 살아남는다면 우리에겐 희망이 있습니다.^^

또 가만히 생각하니 저는 알고 있지만 서버가 1초마다 죽었다 살았다 하니 중간 데이타가 손실 될 것 같은데,,,  연속된 값을 쭉 받으려고 하면
Timer 기능을 정지하는 기능이 필요할 듯.... 저는 필요없습니다. 그 많은 데이타 중 한번씩 멈추고 보거나 중간중간 어느 지점에 ON/OFF만 확인하면 되므로 딱 제 연구용으로 좋습니다. 이번에 글자분수를 대폭 수정했는데... 이놈으로 너무나 편하게 수정했습니다^^

+ -

관련 글 리스트
1159 가상 PLC, IdUDPServer UDP 수신 종료시 먹통 해결방법 박영목.월천 8154 2015/01/31
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.