둘리님 이렇게 자세하게 설명해주셔서 감사합니다!!
다시 열심히 해봐야겠네요~ 아 Indy는 어려워요 ㅜ.ㅜ ㅎㅎ
둘리.CSIEDA 님이 쓰신 글 :
: 원하시지 않는 부분까지 제가 관혀할 일이 아닌데.. 이점 죄송합니다.
: 그냥 제가 보는 관점에서 말씀드립니다..오해 없으셨으면 합니다.
:
: 일단 채팅 샘플을 가지고 시작을 하셨는데요. 어떤 면에서 장비와 채팅을 하는것이라 생각하면 상관은 없습니다만.
:
: 지금 작성하시는 코드가 장비를 컨트롤 하시는것 같습니다.
: 흔히 장비를 PC로 콘트롤 할 경우 장비가 일종의 서버가 되고 PC가 일종의 클라이언트가 됩니다.
: 장비는 분명 server socket 를 열어 pc의 연결을 기다리고 있겠죠. 그런관계로 아래의 프로그램에서 TCP Client Socket 을 사용하신것이고요.
:
: 이런 종류의 프로그램에서 장비와 PC의 통신은 흔히
:
: 1. PC 가 장비에 연결 요청하여 연결 수락 -> 연결 (Socket 하나가 만들어지죠)
: 1.5 장비는 PC로 부터의 수신을 위하여 receive 대기
: 2. PC 가 장비에 질의 (Query, 질의 종류에 따라 2.5로 갑니다)
: 2.5 PC는 Receive 상태로 대기(Indy 이니까 thread 로 들어 갑니다)
: 3. 장비는 PC로부터 데이터를 받아 처리하고 결과를 PC에 응답 (Response)
: 3.5 장비는 1.5로 가겠죠
: 4. PC는 장비로 부터오는 값을 수신
: 4.5 장비로부터 온 값을 처리후 다음 행동 결정하여 5번에 적용하겠죠
: 5. 2번으로 분기 또는 종료
:
: 가 될듯 합니다.
:
: 위의 순서는 대략적으로 적은것입니다만.
: 간단히 PC는 장비에 질의를 하여 그 응답이 있는 질의면 receive 로 빠져야 하고 그렇지 않은 단순 수행 명령
: 이면 다음 행동을 해야 겠죠.
:
: 이러한 시퀀스에서 timer 는 그 용도가 없습니다.
: 채팅 프로그램에 timer 를 쓴다는 것은 P2P 를 약간 흉내내기 위한 것 입니다.
:
: 네트웍 소켓을 이용한 통신 프로그램은 구성상 (FULL / HALF 에 따라서)은 다소 다른구조일 수 있습니다.
:
: 궂이 위와 같이 구성을 않하고 아래의 프로그램과 같이 한다고 해도.. 몇가지 부분이 문제를 일으킵니다.
:
: 우선 타이머가 들어가서 소켓이 receive 대기로 갑니다. (Socket 연결 여부는 사실 여기서 의미가 많이 없습니다, 끊어지면 타이머를 끄셔야 됩니다) , 앞에분이 지적하셨듯이 Connected 를 이중으로 하셨고요. 도는데는 아무 지장 없습니다만...
:
: receive 부분에 try catch 로 timeout 에 대한 처리를 하셨고요.
: timer 를 끄지를 않으시고 receive 로 들어가셨습니다. timeout 걸릴때 또는 연결 자체가 않되었을경우 timer를 끄셨습니다.
:
: timer 와 indy 의 thread은 별개의 것 입니다.
: 이미 indy 가 receive 를 위하여 thread로 들어갔으며 timer 는 계속적으로 돌게 되겠죠.
: receive 로 들어가기 전에 timer를 끄셔야 합니다.
:
: 아래와 같이 어떻게해서든 송수신을 하게 한다고 하여도.. 그 안정성에는 보장을 못할 수 있습니다.
: 정확한 송수신 protocol 규칙을 정하셔서 처리하시는 것이 장비를 보호하고 프로그램이 어느 상황에서든 문제없이
: 돌아가도록 하는 지름길이 아닐까 합니다.
:
: 아래의 코드가 전혀 잘못됬다는 것은 아니니 오해 없으시길 바랍니다...
:
:
:
: Kenzuro 님이 쓰신 글 :
: : 먼저 답변 감사합니다!!
: :
: : 제가 버전을 안 써놨었네요 ㅎ 버전은 Indy9입니다.
: :
: : 아래 코드와 같이 구현하지 않는다는 것을 잘 이해 못하겠습니다.
: :
: : 다른 데모 버전 보니깐 스레드로 구현을 해놨던데..
: :
: : 타이머가 아니라 스레드로서 구현한다는 것인가요?
: :
: :
: :
: : 둘리.CSIEDA 님이 쓰신 글 :
: : : Indy9 인가요? Indy9 blocking mode (indy10 도 마찬가지지만요)라면
: : : 코딩이 잘못 되셨습니다(꼭 잘못된 것은 아니고, 아래의 코드와 같이 구현하지 않거든요).
: : : 우선 확인 부탁 합니다.
: : :
: : :
: : :
: : : Kenzuro 님이 쓰신 글 :
: : : : 안녕하세요 Builder 초보 Kenzuro 입니다.
: : : :
: : : : 장비에서 값을 받아오는데.. 시간값을 명령어로 보내면 장비에서 데이터를 보내 주고 있습니다.
: : : :
: : : : 기본 소켓으로는 잘 되고 있었는데요. 그것을 인디로 바꾸 싶어서 공부를 하고 있습니다.
: : : :
: : : : 데이터는 D,M1,N001,40,30,40,0,N002.... 이런식으로 들어오는데 N060까지 들어옵니다.
: : : :
: : : : 채팅 데모 버전을 약간 수정해서 만들어봤는데요. 장비에 명령어를 보내도 감감 무소식입니다..
: : : :
: : : : 값을 받는 방법이 틀린건가요?? 도움 좀 주세요~
: : : :
: : : : 제가 만든 소스 첨부하겠습니다.
: : : :
: : : :
__fastcall TForm1::TForm1(TComponent* Owner)
: : : : : TForm(Owner)
: : : : {
: : : :
: : : : IdSocketClient->Host = "192.168.0.50";
: : : : IdSocketClient->Port = 5001;
: : : : IdSocketClient->Connect();
: : : : Sleep(1000);
: : : :
: : : : if(IdSocketClient->Connected() == true){
: : : : ReceiveMemo->Lines->Add("Socket Connect Success\n================================\n");
: : : : }else{
: : : : ReceiveMemo->Lines->Add("Socket Connect fail\n================================\n");
: : : : }
: : : : }
: : : : //---------------------------------------------------------------------------
: : : :
: : : : void __fastcall TForm1::SendMessageClick(TObject *Sender)
: : : : {
: : : : if(SendEdit->Text != ""){
: : : : IdSocketClient->WriteLn(SendEdit->Text);
: : : : Sleep(100);
: : : : ReceiveMemo->Lines->Add("Send : " + SendEdit->Text+ "\n================================\n");
: : : : SendEdit->Text = "";
: : : : }
: : : : }
: : : : //---------------------------------------------------------------------------
: : : : void __fastcall TForm1::ReceiveTimerTimer(TObject *Sender)
: : : : {
: : : : if(IdSocketClient->Connected()){
: : : : static int errorcnt = 0;
: : : : AnsiString Msg;
: : : :
: : : : if(!IdSocketClient->Connected())
: : : : return;
: : : :
: : : : try{
: : : : Msg = IdSocketClient->ReadLn("", 5);
: : : : //IdSocketClient->ReadBuffer(Msg, 1024)
: : : : }catch(...){
: : : : errorcnt++;
: : : : if(errorcnt > 4){
: : : : ReceiveTimer->Enabled = false;
: : : : ReceiveMemo->Lines->Add("IdSocketClient Error\n================================\n");
: : : : }
: : : : }
: : : :
: : : : if(Msg != ""){
: : : : ReceiveMemo->Lines->Add("Recv : " + Msg +"\n================================\n");
: : : : Msg = "";
: : : : }
: : : : }else{
: : : : ReceiveTimer->Enabled = false;
: : : : ReceiveMemo->Lines->Add("IdSocketClient DisConnect\n================================\n");
: : : : }
: : : : }