학교에서 네트워크 수업하다가
간단한 프로그램 만들어 보려고 Indy 9 컴포넌트를 사용해보게 되었어요.
포인터 구조체에 패킷을 넣고, 서버에서 받아서 처리하기 위해서 Flag 를 넣고 Data를 보내도록~
그런데 포인터 구조체를 보내고 받고 하는 부분이 잘 안되서 도움을 받을수 있을까 해서 이렇게 글을 올려 봅니다.
포인터 구조체는 다음과 같이 코딩햇습니다.
type
TSocketDataHeader = record
Flag : Word; //플래그
Size : Integer; //데이터 사이즈
end;
TSocketData = record
Header : TSocketDataheader; //헤더정보
Data : Pointer; //데이터
end;
pSocketData = ^TSocketData;
메시지를 보내는 클라이언트 녀석을 요렇게 했죠
procedure TForm1.btnConnectClick(Sender: TObject);
var
pPacket : pSocketData;
pData : ^string;
Data : string;
begin
{포인터 구조체 활당}
New(pPacket);
{보낼 메시지}
Data := 'Client Message';
pData := @Data;
pPacket^.Header.Flag := 0;
pPacket^.Data := pData;
ppacket^.Header.Size := Length(Data);
{서버에 접속}
IdTCPClient1.Connect;
{서버에 메시지 보내기}
IdTCPClient1.WriteBuffer(pPacket^, SizeOf(pPacket), True); //<< 안됨
OutputDebugString(PCHAR(Format('%d', [SizeOf(pPacket)])));
{포인터 구조체 메모리 해제}
Dispose(pPacket);
end;
서버에서 메시지를 받을 때 처리는 다음과 같이 했습니다.
procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
var ClientInfo :TClientInfo;
MessageClient : string;
pPacket : pSocketData;
begin
ClientInfo := Pointer(AThread.Data);
if ClientInfo = nil then Exit;
{포인터 구조체 초기화}
New(pPacket);
try
{패킷의 헤더 사이즈를 읽는다}
AThread.Connection.Readbuffer(pPacket^.Header, SizeOf(pPacket^.Header));
{헤더 사이즈가 있을경우}
if pPacket^.Header.Size > 0 then
begin
{받을 데이터의 크기만큼 메모리 활당}
GetMem(pPacket^.Data, pPacket^.Header.Size);
{데이터를 읽는다}
AThread.Connection.ReadBuffer(ppacket^.Data^, ppacket^.Header.Size);
end;
{포인터형 변수를 텍스트로 읽는다}
MessageClient := DataToText(pPacket^.Data, pPacket^.Header.Size);
{메시지 출력}
memo1.Lines.Add(MessageClient);
{플래그별 메소드 실행}
case pPacket^.Header.Flag of
0 : Memo1.Lines.Add('Client Flag : 0');
1 : Memo1.Lines.Add('Client Flag : 1');
end;
except
{이상한 문자가 오면 정지}
AThread.Stop;
end;
{포인터 구조체 해제}
Dispose(pPacket);
end;
코드상에선 에러없이 컴파일되고, 실행되 잘됩니다.
커넥선, 디스커넥션 메시지도 잘 처리 되는데, 이상하게 WriteBuffer 와 ReadBuffer가 메시지 처리가 안되네요.
첨부파일에 소스코드 올립니다.
OutPutBin : ../
포인터를 보내면 안됩니다. 포인터의 내용을 보내야죠... 포인터는 현재 프로그램내에서만 유효한 값입니다.
또한 SizeOf(포인터)는 항상 4입니다. (SizeOf(pPacket) ==4)
서버에서 받을때처럼 두번에 나눠서 보내시던가 구조체를 포인터없이 데이터만 담을수 있도록 변경하세요. (TSocketData.Data가 포인터입니다.)