일반적인 쓰레드는 사용해봤지만 통신에서는 사용해보질 않았습니다.
예를 들어서 PLC와 시리얼 통신을 하고자 할 경우
제가 찾아본 소스들을 보면 SendText 쪽에는 쓰레드를 걸어주던데
왜 Receive쪽에는 쓰레드를 멈춰주는지 조금 이해가...
1) 그럴 경우에는 Send 전문을 구성하는 중에 Receive가 들어올 경우 어떻게 될까요?
2) 또는 Send전문을 구성한 후 Send 작업중에 Receive가 들어오면 어찌되는지...
3) Receive된 메세지를 처리하고있을 경우 또다른 Receive가 들어오면 어찌될까요?
진행되는 도중에 Event가 도착했다고 다시 첨부터 시작하지는 않겠지요?
4) TCP/IP의 경우 블로킹 모드를 사용하면 따로 쓰레드를 돌릴 필요가 없나요?
IndyTCP의 경우에는 ThreadMgr을 붙일 경우에 쓰레드를 쓸 필요가 없나요?
고수님들의 조언을 바랍니다...
아래는 미완성인 예제 소스입니다.
별 도움은 안될테지만 참고를 하실 수 있으면 해보시라고...
//Send부분
function Transfer_Command_SC4(P : Pointer):LongInt;StdCall;
var
TxB : TSendBuffer;
CrcSum : WORD;
i : Integer;
begin
EnterCriticalSection(CSection);
//Send 및 Receive 작업
SetLength(Txb,8);
Txb[0] := 01;
Txb[1] := $64;
Txb[2] := 01;
Txb[3] := 03;
Txb[4] := 00;
Txb[5] := 00;
Txb[6] := 04;
CrcSum := Send.Crc_Check(Txb,6);
Txb[7] := CRCSum And $00FF;
Txb[8] := CRCSum Shr 8;
Send.SC_Send_Data := '';
for i := 0 to 8 do
Send.SC_Send_Data := Send.SC_Send_Data + IntToHex(Txb[i],2);
Send.CommSC4.SendString(Send.SC_Send_Data);
LeaveCriticalSection(CSection);
Result := 0;
end;
//Receive 부분
procedure TSend.CommSC1ReceiveData(Sender: TObject; DataPtr: Pointer;
DataSize: Cardinal);
var
s : string;
CopyS : string;
CrcSum, CRC1, CRC2 : Word;
RxB : TSendBuffer;
Len : Integer;
i,j : Integer;
begin
chkReadFlag := True;
chkRetrySC1 := 1;
s := StringOfChar( ' ', DataSize );
move( DataPtr^, PChar(s)^, DataSize );
CopyS := Copy(s,1,2);
SetLength(RxB,3);
RxB[0] := StrToInt(Copy(s,1,2)); //SA No
RxB[1] := StrToInt(Copy(s,3,2)); //DA No
RxB[2] := StrToInt(Copy(s,5,2)); //명령코드에 응답임을 표시
RxB[3] := StrToInt(Copy(s,7,2)); //CRC부분을 제외한 부분의 Length
Len := RxB[3];
Len := Len + 3 + 2;
SetLength(RxB, Len);
i := 1;
j := 9;
while i <= (Len-3) do begin
RxB[i+3] := StrToInt(Copy(S,j,2));
i := i + 1;
j := j + 2;
end;
CrcSum := Crc_Check(RxB,Len-2);
CRC1 := CRCSum And $00FF;
CRC2 := CRCSum Shr 8;
if (CRC1 = RxB[Len-1]) and (CRC2 = RxB[Len]) then begin //CRC Check가 맞으면
end
else begin //CRC Check가 맞지 않으면
end;
end;
즉, 쓰레드 하나를 돌려놓고 평소에는 읽기만 하다가...
OnRecieveData 이벤트가 발생하면 그때 쓰레드를 Suspend 시켜놓고
들어온 데이터를 분석하고 분석이 끝나면 다시 Resume을 시켜주면 됩니다..
그러면 Cpu 사용율도 줄어들고 매우 빠른 통신을 수행하지요..
그런데 읽기 통신 하고 있는디 과연 언제 쓰기통신을 수행하는가?
즉 Send 작업 중 읽기 통신을 하고 있으면 들어오고 있는 패킷은 어찌되는가?
요런 물음을 던질 수 밖에 없습니다.
이때는 큐를 사용하십시오..
읽기나 쓰기통신할 때 바로 패킷을 전송하지말고.. 무조건 큐에 집어넣는 겁니다.
평소에는
읽기통신 순번이나 최소한의 정보만을 큐에 집어넣고
이 큐에 들어오는 순서대로 읽기통신을 하거나 쓰기통신을 하십시오...
주의점은
읽기통신패킷이나 쓰기통신 패킷을 전송한 직후..
쓰레드는 Suspend시키는 겁니다..
그럼 패킷은 전송되고 뭔가 응답이 오겠죠?
OnReceiveData에 응답이벤트가 걸리면.... 그 분석처리를 완성하고...
비로소 쓰레드를 Resume시키는 것이 키포인트가 되겠습니다.
이러한 예나 소스를 구경하려면...
myhome.shinbiro.com/~opencomm에 들러서 강좌를 읽어보시던가..
OpenFAVCL 패키지를 다운받아서 통신VCL들의 소스를 참고하시면
원하시는 답을 얻을 수 있으실거 같군요..
최철민 wrote:
> 일반적인 쓰레드는 사용해봤지만 통신에서는 사용해보질 않았습니다.
> 예를 들어서 PLC와 시리얼 통신을 하고자 할 경우
> 제가 찾아본 소스들을 보면 SendText 쪽에는 쓰레드를 걸어주던데
> 왜 Receive쪽에는 쓰레드를 멈춰주는지 조금 이해가...
> 그럴 경우에는 Send 전문을 구성하는 중에 Receive가 들어올 경우 어떻게 될까요?
> 또는 Send전문을 구성한 후 Send 작업중에 Receive가 들어오면 어찌되는지...
> 고수님들의 조언을 바랍니다...
>
> 아래는 미완성인 예제 소스입니다.
> 참고를 하실 수 있으면 해보시라고...
>
>
> //Send부분
> function Transfer_Command_SC4(P : Pointer):LongInt;StdCall;
> var
> TxB : TSendBuffer;
> CrcSum : WORD;
> i : Integer;
> begin
>
> EnterCriticalSection(CSection);
> //Send 및 Receive 작업
> SetLength(Txb,8);
> Txb[0] := 01;
> Txb[1] := $64;
> Txb[2] := 01;
> Txb[3] := 03;
> Txb[4] := 00;
> Txb[5] := 00;
> Txb[6] := 04;
> CrcSum := Send.Crc_Check(Txb,6);
> Txb[7] := CRCSum And $00FF;
> Txb[8] := CRCSum Shr 8;
> Send.SC_Send_Data := '';
>
> for i := 0 to 8 do
> Send.SC_Send_Data := Send.SC_Send_Data + IntToHex(Txb[i],2);
>
> Send.CommSC4.SendString(Send.SC_Send_Data);
> LeaveCriticalSection(CSection);
> Result := 0;
>
> end;
>
>
> //Receive 부분
> procedure TSend.CommSC1ReceiveData(Sender: TObject; DataPtr: Pointer;
> DataSize: Cardinal);
> var
> s : string;
> CopyS : string;
> CrcSum, CRC1, CRC2 : Word;
> RxB : TSendBuffer;
> Len : Integer;
> i,j : Integer;
> begin
>
> chkReadFlag := True;
> chkRetrySC1 := 1;
> s := StringOfChar( ' ', DataSize );
> move( DataPtr^, PChar(s)^, DataSize );
> CopyS := Copy(s,1,2);
> SetLength(RxB,3);
> RxB[0] := StrToInt(Copy(s,1,2)); //SA No
> RxB[1] := StrToInt(Copy(s,3,2)); //DA No
> RxB[2] := StrToInt(Copy(s,5,2)); //명령코드에 응답임을 표시
> RxB[3] := StrToInt(Copy(s,7,2)); //CRC부분을 제외한 부분의 Length
> Len := RxB[3];
> Len := Len + 3 + 2;
> SetLength(RxB, Len);
>
> i := 1;
> j := 9;
> while i <= (Len-3) do begin
> RxB[i+3] := StrToInt(Copy(S,j,2));
> i := i + 1;
> j := j + 2;
> end;
>
> CrcSum := Crc_Check(RxB,Len-2);
> CRC1 := CRCSum And $00FF;
> CRC2 := CRCSum Shr 8;
> if (CRC1 = RxB[Len-1]) and (CRC2 = RxB[Len]) then begin //CRC Check가 맞으면
> end
> else begin //CRC Check가 맞지 않으면
>
> end;
>
> end;