Q&A

  • Stream에서 데이터 읽어들이기...
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;

2  COMMENTS
  • Profile
    최용일 2008.12.05 00:55
    보내는 부분에서 잘못된 곳이 있네요...
    동적 배열 (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;
  • Profile
    cell 2008.12.05 01:24
    맞네요... 동적배열이 포인터형인데... 먼짓을 한건지...^^
    감사합니다.
    • 김길현
    • 2008.12.05 01:45
    • 0 COMMENTS
    • /
    • 0 LIKES
    • 최용일
      2008.12.05 01:05
      추측하자면... UDP1.GetMessage(str);에서 타임아웃되어서 종료되고 이 때문에 str에는 아무 값도 설정...
    • absurdite
      2008.12.05 02:22
      앗! 딱 맞습니다ㅡㅜ UDP1.GetMessage(str); if (not (str = '')) then Memo1.Lines.Add(str); ...
    • cell
    • 2008.12.04 23:22
    • 2 COMMENTS
    • /
    • 0 LIKES
    • 최용일
      2008.12.05 00:55
      보내는 부분에서 잘못된 곳이 있네요... 동적 배열 (array of ...)은 포인터형입니다. 실제 데이터는 다...
    • cell
      2008.12.05 01:24
      맞네요... 동적배열이 포인터형인데... 먼짓을 한건지...^^ 감사합니다.
    • 별이^^
    • 2008.12.04 18:51
    • 0 COMMENTS
    • /
    • 0 LIKES
    • 이건희
    • 2008.12.03 20:59
    • 1 COMMENTS
    • /
    • 0 LIKES
    • 장성호
      2008.12.03 22:08
      Timer를 이용해보세요 1. OnMouseDown이벤트에서 1.1 레이블의 숫자를 증가시키세요 ...
    • 까마귀
      2008.12.03 23:26
      흠... 아마 메인폼 실행후에 로그인 창이 뜨도록 만들어져 있는 것 같네요. 그리고, 메인폼 실행시 쿼...
    • 이정욱
      2008.12.03 12:57
      클래스를 사용하면 좋겠지만, 만약 네트웍이나 시리얼을 통해 자료를 주고 받는 다면 packed record를 사...
    • 이은주
      2008.12.03 15:45
      아 그럼 동일한 환경이라면 클래스를 쓰는 것이 유리하고 정보를 전송하는 경우는 packed record 가 유리...
    • 김명민
    • 2008.12.03 06:10
    • 0 COMMENTS
    • /
    • 0 LIKES
    • cell
    • 2008.12.03 04:38
    • 2 COMMENTS
    • /
    • 0 LIKES
    • 최용일
      2008.12.03 07:21
      쩝~ 왜 꼭 4바이트 형태로 만들어야 된다고 생각하시는지요? Byte든 Char 이든, 16진수이든 10진수이든...
    • cell
      2008.12.04 22:31
      최용일님 말씀처럼 너무 4바이트에 연연했나보네요 ^^ 잘해겼됐습니다.
    • Jackie
    • 2008.12.03 03:09
    • 3 COMMENTS
    • /
    • 0 LIKES
    • 최용일
      2008.12.03 03:25
      왜 겹치려고 하는지는 모르겠지만.... TLabel은 절대 TPageControl위로 올라갈 수가 없습니다. TLabel...
    • Jackie
      2008.12.03 03:43
      님의 덕분에 해결을 하였습니다. 정말 감사합니다. 두 콤포넌트가 겹치는것은 대면부구성상 탭오른...
    • 장성호
      2008.12.03 04:02
      TLabel 과 TSpeedButton은 Graphic-Control(윈도우핸들이 없는놈)입니다. 그리고 TPageControl 과 TSt...
    • 꼬꼬마
    • 2008.12.02 21:50
    • 2 COMMENTS
    • /
    • 0 LIKES
    • 최용일
      2008.12.02 22:39
      아래와 같이해서 함수를 하나 만들어 쓰세요. 1. 년도와 월 가지고 그달의 1일을 구하세요. (EncodeDate...
    • 꼬꼬마
      2008.12.02 23:44
      휴...;;; 무슨 말인지는 알겠는데요;; 아직 델 초보라서;;; 이것저것 계속 해보고 있는데;;;;; ...
    • 장성호
    • 2008.12.02 23:53
    • 1 COMMENTS
    • /
    • 0 LIKES
    • 꼬꼬마
      2008.12.03 00:53
      장성호님..최용일님.. 두분 감사합니다..;; 몇일째 고생했던게;;;; 시원하게 풀렸네요... 여기서 멈...
    • cell
    • 2008.12.02 06:16
    • 1 COMMENTS
    • /
    • 0 LIKES
    • 최용일
      2008.12.02 18:58
      동적 배열을 사용해보세요. A+B+C+D만큼의 크기를 동적배열로 잡고 거기에 데이터를 넣어서 전송하시면 ...
    • 꼬꼬마
    • 2008.12.01 22:10
    • 3 COMMENTS
    • /
    • 0 LIKES
    • 최용일
      2008.12.02 02:14
      뭐가 잘 안된다는 것인지.... 그냥 for문으로 원하시는 주를 삽입하시면 될것 같은데요...
    • 꼬꼬마
      2008.12.02 04:01
      어떤 식으로... for문을 돌려야 하는건가요? 이거..그냥 계속 제자리 걸음을 하는거 같네여;; ㅠㅜ
    • 장성호
      2008.12.02 05:03
      벌써 여러번 같은 질문 올리셨죠? 이곳 말고 델마당에도... http://www.delphi.co.kr/zboard/view....
    • 조일현
    • 2008.12.01 21:16
    • 3 COMMENTS
    • /
    • 0 LIKES
    • 최용일
      2008.12.02 02:16
      뭘 그렇게 숨기시려고 하시는지... 'zzzzzz'이란 에러메세지에 해답이 있습니다. 잘 분석해보세요.
    • 아르스
      2008.12.02 19:09
      ^^
    • 조일현
      2008.12.07 20:36
      감사합니다~~
    • 백록화
      2008.12.01 19:52
      흠... DataSet - DataSource - DbGrid 이렇게 연결되어 있는 상태에서 DbGrid 의 Row가 변경이 되...
    • 델파이쌩초보
      2008.12.02 00:55
      백록화님 먼저 관심이 갖고 답변을 해주셔서 너무 감사드립니다. 진작 들어와봤으면 좋았을껄.. ㅎㅎ ...
    • 백록화
      2008.12.02 04:14
      네...각 콤포넌트들 (TDataSet, TDataSource, TDbGrid) 는 서로 유기적으로 묶여져 있습니다. 따라서 어...
    • 델파이쌩초보
      2008.12.04 20:34
      백록화님 정말 감사드립니다. 한번에 정확히 이해를 못하고는 있지만.. 약간 감은 오는 것 같습니다. ...
    • 유경민
    • 2008.11.29 22:54
    • 1 COMMENTS
    • /
    • 0 LIKES
    • safebear
      2008.12.01 19:07
      자료실에 원하시는게 있네요 ^^ http://www.delphi.co.kr/zboard/view.php?id=component&page=1&sn1=&...