type
TPacket = packed record
MC : array [0..3 ] of Char;
PV : array [0..3 ] of Char;
DL : array of Byte;
DATA : Array of Char;
CS : array of Byte;
end;
PTPacket = ^TPacket;
서버에서 받아보면
procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
var aStream : TMemoryStream;
InBuf : TPacket;
TotLen : LongWord;
begin
Try
aStream := TMemoryStream.Create;
AThread.Connection.ReadStream(aStream, -1, false);
aStream.Position := 0;
AStream.ReadBuffer(InBuf, 8);
TotLen := 0;
aStream.Position := 8;
SetLength(InBuf.DL, SizeOf(TotLen));
AStream.ReadBuffer(InBuf.DL[0], SizeOf(TotLen));
Move(InBuf.DL[0], TotLen, SizeOf(TotLen));
Memo1.Lines.Add(IntToStr(TotLen))
Finally
aStream.Free;
end;
end;
InBuf.DL 부분은 어떻게 읽어야 하나요? 실제 값은 32가 들어있습니다.
똑같은 데이터를 전송해도 위 처럼 MOVE를 하니 10111596, 10109792, 10116848 이렇게 다른 값이 나옵니다.
클라이언트에서 AStream.WriteBuffer(OutBuf, totLen) 하기 전에 Move로 확인해면 정상적인 값이 나옵니다.
AStream.WriteBuffer 한 후 다시 ReadBuffer 해보면 위와 같이 8자리 숫자로 나오네요.
레코드 타입전에 동적배열(Byte형) 하나로 통신했을때 위와같이 해도 32라는고 나왔던걸로 기억되는데
레코드 타입으로 바꾼뒤에는 안되네요...
아래는 클라이언트 소스입니다.
procedure TForm1.Button1Click(Sender: TObject);
var OutBuf : TPacket;
TotLen : LongWord;
pPos, I : Integer;
Data, WorkType : String;
AStream: TMemoryStream;
s : LongWord;
begin
if Socket_connect then
begin
Try
AStream := TMemoryStream.Create;
if RadioButton1.Checked Then WorkType:= 'A'
else if RadioButton2.Checked Then WorkType := 'B'
else WorkType := 'C';
Data := WorkType + FormatCurr('0000', Length(Edit1.Text + '|' + Edit2.Text + '|' + Edit3.Text + '|' + Edit4.Text)) +
Edit1.Text + '|' + Edit2.Text + '|' + Edit3.Text + '|' + Edit4.Text;
OutBuf.MC := 'ABCD';
OutBuf.PV := '1234';
TotLen := Length(Data) + SizeOf(SizeOf(TotLen));
SetLength(OutBuf.DATA, Length(Data));
SetLength(OutBuf.DL, SizeOf(TotLen));
SetLength(OutBuf.CS, SizeOf(TotLen));
Move(Data[1], OutBuf.Data[0], Length(Data));
Move(TotLen, OutBuf.DL[0], SizeOf(TotLen));
Move(TotLen, OutBuf.CS[0], SizeOf(TotLen));
AStream.WriteBuffer(OutBuf, totLen);
IdTCPClient1.WriteStream(aStream, True, True, aStream.Size);
Finally
AStream.Free;
end;
end;
Socket_disconnect;
end;
동적 배열 (array of ...)은 포인터형입니다. 실제 데이터는 다른 메모리 번지에 있고 변수자체에는 메모리 번지값만 들어가 있습니다.
동적배열과 같이 포인터형이 포함된 레코드변수를 TCP로 보내봤자 상대방에서는 그 값을 읽을 수 있는 방법이 없습니다. 실제 값은 보낸쪽에 있고 메모리 번지만 받으니까요...
TPacket구조체의 DL, CS필드는 코드를 보면 굳이 동적배열로 안해도 될듯한데요. TotLen이 들어가는 것을 보면 그냥 LongWord로 선언하셔도 될듯합니다.
뭐 꼭 그렇게 해야될 이유가 있다면 어쩔 수 없지만...
되도록 구조를 안바꾸는 선에서 고쳐보자면...
// 보내는 쪽
procedure TForm1.Button1Click(Sender: TObject);
var
......
begin
......
// AStream.WriteBuffer(OutBuf, totLen); ==> 아래와 같이
AStream.WriteBuffer(OutBuf, SizeOf(OutBuf.MC) + SizeOf(OutBuf.PV) ); // Write MC & PV field
AStream.WriteBuffer(OutBuf.DL[0], Length(OutBuf.DL) ); // Write DL field
AStream.WriteBuffer(OutBuf.Data[0], Length(OutBuf.Data) ); // Write Data field
AStream.WriteBuffer(OutBuf.CS[0], Length(OutBuf.CS) ); // Write CS field
......
end;