Q&A

  • socket 통신에서 동기식 소켓 통신을 구현하려면
delphi를 시작한지 1달 정도 되었습니다.

다름이 아니오라 소켓통신은 동기식과 비동기식으로 나뉜다고 들었습니다.

동기식 통신을 하기 위해서 우선 클라이언트에서 메시지를 '##보낼분자열길이@@보낼문자열' 으로 서버쪽에 보내서 서버쪽에서는 클라이언트쪽에서 보낸 메시지를 받아 그값이 정상적으로 들어왔나를 체크해서 만약 들어오지 않았을 경우는 해당 클라이언트에세 메시지가 정상적으로 도착하지 않았음을 알리고 해당 메시지를 다시 보내라는 것을 구현하기 위해서는 어떻게 해야할지 잘 모르겠습니다.

아시는분 계시면 답변 좀 부탁드리겠습니다.

--------Client에서 보내는 부분
procedure TForm1.memSendKeyPress(Sender: TObject; var Key: Char);
var
  SendMsg : string;
  i: Integer;
begin
  if key = #13 then
  begin
    if ClientSocket1.Active then
    begin
      key := #0;
      for i := 0 to 99 do
      begin
      SendMsg := '##'+ format('%10d', [length(Form1.memSend.Text)]) + '@@';
            SendMsg := SendMsg + Form1.memSend.Text;
      end;
      ClientSocket1.Socket.SendText(SendMsg);
      form1.memSend.Lines.Clear;
      form1.memSend.SetFocus;
      form1.memSend.SelStart := 0;
    end
    else
    begin
      memReceive.Lines.Add('Cannot send message when disconnected!');
      form1.memSend.Lines.Clear;
      form1.memSend.SetFocus;
      form1.memSend.SelStart := 0;
    end;
  end;
end;


----Server에서 받는 부분
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
var
  ReceiveMsg, body_data : string;
  st, en, i, j, body_length : integer;
begin
  ReceiveMsg := Socket.ReceiveText;
  body_data := ReceiveMsg;
  st := pos('##', ReceiveMsg);
  en := pos('@@', ReceiveMsg);
  if (st > 0 ) and (en > 0) then
  begin
    //  ##0000000000@@
    body_length := StrToInt(copy(ReceiveMsg, st + 2, 10));
    body_data := copy(ReceiveMsg, en+2, 100000);
  end;
  if length(body_data) = body_length then
  begin
    ReceiveMsg := body_data;
    Socket.SendText('##'+format('%10d', [length(ReceiveMsg)])+'@@'+ReceiveMsg);
    Form1.memReceive.Lines.Add('##'+format('%10d', [length(ReceiveMsg)])+'@@'+ReceiveMsg);
  end;
  if length(body_data) > body_length then
  begin
    Form1.memReceive.Lines.Add('!ERROR');
  end;
end;
1  COMMENTS
  • Profile
    한원희 2002.09.03 06:38
    안녕하세요. 한원희입니다.

    TCP를 이용하시는 것이라면, 잘못된 데이터의 전송에 대한 고려를 하지 않으셔도 됩니다. 지금은 전송 기술도 많이 발달되어 있고, TCP 자체가 오류에 의해서는 자동으로 재전송등을 내부적으로 처리해 주는 프로토콜이기 때문입니다. UDP로 작성을 하신다면 모르겠지만 말이죠. ^^;

    동기식 소켓을 따로 구현하실 필요는 없구요. 이미 유용한 컴포넌트들이 많이 있습니다. 뭐 요새는 인디를 많이 사용하더군요. 별로 추천하고 싶지는 않지만...(너무 무거운 패키지인지라...)

    동기식으로 처리를 한다면, 꼭 쓰레드로 처리를 하셔야 합니다. 뭐 꼭은 아니지만, 서버에서 데이터를 수신할 때까지 프로그램이 멈춰있어도 상관없다면 말이죠. ^^; 비동기식으로 처리를 한다면 상관없겠죠. 데이터를 수신하는 이벤트만 처리하면 되니까요.

    아래의 코드를 보면, 클라이언트 측에서 100번 계속 데이터를 송신하고, 서버측에서 수신을 하는데, 클라이언트에서 100번 송신했다고 해서 서버측에서 100번 수신하지는 않습니다. 연속적으로 데이터를 보내는 경우, 내부 버퍼의 크기와 TCP 패킷의 크기에 따라서, 실제로 보내는 양보다 많게 갈 수가 있기 때문에, 아마도 실제로는 100번보다 적게 받게 될겁니다. 그렇다고 클라이언트에서 보낸 데이터를 잃는 것은 아니고, 100번에 보낸 데이터를 몇몇 개가 합쳐져서 더 적은 수의 패킷으로 날아오게 되죠. 이것 프로토콜을 설계한 사람들이 데이터를 좀더 효율적으로 보내기 위해서, 조금씩 많이 보내는 비효율적인 상황을 줄이기 위해서, 한 패킷이 최대 보낼 수 있는 양을 다 채워서 보내게끔 되어 있기 때문이지요.

    그렇기 때문에, 아래와 같은 코딩은 잘 못된 것입니다. 아래와 같은 코딩을 적용하기 위해서는 내부적으로 버퍼를 유지하고 있는 다른 컴포넌트를 사용하셔야 합니다. 그런 컴포넌트중의 하나가 인디입니다. 대부분의 동기식 코딩(한줄 단위의 전송)에서 주로 인디를 사용하더군요. 내부적으로 버퍼를 처리해주니까, 프로그래머가 그 부분을 신경써 주지 않아도 되기 때문이죠. 이러한 인디에 대한 예는 많으니까, 한번 찾아보시구요.

    인디를 사용하셔서 코딩하시면 쉽게 구현하실 수 있으리라 생각됩니다.
    생각 나는대로 마구 적어서 틀린 내용이 있을 겁니다.
    그런 부분은 애교로 봐주시고... 이만 허접한 답변을 접겠습니다. ^^;

    • 전원보
    • 2002.09.03 10:09
    • 2 COMMENTS
    • /
    • 0 LIKES
    • 박장용
      2002.09.03 19:44
      텍스트 파일에 한정된다면 Memo나 RichEdit로 읽어 들이시는게 편합니다.   RichEdit1.Lines....
    • 세균맨
      2002.09.03 19:43
      글쎄요.....특정문자의 인덱스라면 구분자를 말씀하시는 것인지..... 모르겠군요.... 만약 구분자를 말씀...
    • 마니산
    • 2002.09.03 08:55
    • 1 COMMENTS
    • /
    • 0 LIKES
    • 최용일
      2002.09.03 09:19
      안녕하세요. 최용일입니다. 1입니다. 둘다 정수형이고 Byte에서 Integer로 형변환할때 절대 범위를 넘는...
    • sunny
    • 2002.09.03 08:26
    • 2 COMMENTS
    • /
    • 0 LIKES
    • 최용일
      2002.09.03 09:41
      안녕하세요. 최용일입니다. 아래와 같이 해보세요... 좀 더 많이 책보고 VCL에 대해서 공부하셔야 할듯....
    • sunny
      2002.09.03 14:29
      감사합니다. 당장 이렇게 해결하는것만이 최선의 방법은 아닌줄 압니다. 열심히 노력하겠습니다. 그럼...
    • 최용일
      2002.09.03 09:44
      안녕하세요. 최용일입니다. File메뉴에서 프로젝트를 저장하세요... 임의로만든 프로젝트폴더에... ...
    • 한창훈
    • 2002.09.03 07:14
    • 1 COMMENTS
    • /
    • 0 LIKES
    • 이추형
      2002.09.03 23:02
      PL/SQL을 구현해야 하지만 파라독스에서 지원이 되는지는 정확히 모르겠습니다. (오라클등등의 대용량 DB...
    • 배창석
      2002.09.18 08:08
      델파이 소스가 있는 디렉토리의 경로에 '('등의 특수문자가 포함되어있는 지 확인해보세요... 있다면, 제...
    • 이추형
      2002.09.04 01:19
      BDE에서 설정한 Alias name이 'Oracle_DB'인지 확인하시기 바랍니다. 혹 다른이름으로 되어 있는건 아닌지...
    • goodlsw
    • 2002.09.03 05:26
    • 1 COMMENTS
    • /
    • 0 LIKES
    • 한원희
      2002.09.03 05:51
      안녕하세요. 한원희입니다. 캐럿의 위치를 구하기 위해서는 GetCaretPos 라는 API를 사용하시면 됩니다....
    • 김상수
    • 2002.09.03 04:58
    • 8 COMMENTS
    • /
    • 0 LIKES
    • 임형호
      2002.09.03 05:19
    • 김상수
      2002.09.03 05:25
    • 임형호
      2002.09.03 10:37
    • 김상수
      2002.09.03 19:23
    • 임형호
      2002.09.03 22:03
    • 김상수
      2002.09.04 01:45
    • 임형호
      2002.09.04 05:43
    • • • •
    • 한원희
      2002.09.03 05:38
      안녕하세요. 한원희입니다. 서브클래싱이나 윈도우 후킹을 하면 가능할 것 같습니다. 좀 복잡하니까, ...
    • ㄴ ㅏ ㅁ ㅑ
      2002.09.03 19:57
      먼저 답변 감사드립니다 ^o^ procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;  &...
    • 한원희
      2002.09.03 23:49
      안녕하세요. 한원희입니다. 아쉽게도 VK_BACK는 네비게이션 키로 분류되어 있어서 방향키 등과 같이 Key...
    • 임형호
      2002.09.03 05:15
      keypress에서는 잘 모르겠구요. keydown이벤트에서는 if key=46 then   key = 0; ...
    • 김상수
    • 2002.09.03 04:28
    • 1 COMMENTS
    • /
    • 0 LIKES
    • 임형호
      2002.09.03 04:41
      예.. 콤보박스로 그렇게 하면 됩니다.
    • 한원희
      2002.09.03 06:23
      안녕하세요. 한원희입니다. 아래 코드에서 약간 이해가 안가는 부분이 있는데, 수신측에서 데이터의 전...
    • 홍성락
      2002.09.03 06:10
      hsr/////////////////////////////////////////////////// 간단히 DBGrid에 연결된 PopupMenu가 열리는 시...
    • 델파이사랑
      2002.09.03 20:51
      ....^^....^^....^^
    • 고지범
      2002.09.03 03:25
      지나가던 얼큰입니다. 제 생각에는 델파이나 VC++ 이나 가장 좋은 것은 Update Handler 를 이용하는 것이 ...
    • 짱아
    • 2002.09.03 00:55
    • 2 COMMENTS
    • /
    • 0 LIKES
    • 이추형
      2002.09.03 01:21
      TStringGrid.Cells 의 ACol과 ARow를 Loop 돌면서 파일 하나하나 처리 하셔야 할것 같습니다. .. 가장 쉬...
    • 짱아
      2002.09.03 02:37
      ㅡㅡ; 자세히점.. 갈켜 주시겠어염...
    • 고부열
      2002.09.03 03:30
      해당 폼의 버튼 속성중이 Default 가 true로 되어있더군요. 제 친구중에 델파이의 거의 달인이 있는데...
    • 고지범
      2002.09.03 03:44
      클클... 추카합다... 그런 일두 ^^
    • 고지범
      2002.09.03 01:28
      지나가던 얼큰입다. 잘 되는 데요??? KeyDown Event 에서 다음과 같이 하믄... 잘 올라오던디... procedu...
    • 이추형
      2002.09.03 01:28
      procedure TForm1.Edit1KeyDown(Sender: TObject; var Key: Word;   Shift: TShiftState); beg...
    • 고부열
      2002.09.03 01:32
      답변 감사드립니다. // -- 아래는 제가 작성한 소스 코드입니다.       ...
    • 고지범
      2002.09.03 02:11
      윽... MDI child 에서두 잘 들어가 지는 데... 무엇이 다른지 모르겠군요... 테스트를 편하게 하기 위해서...
    • 고부열
      2002.09.03 02:57
      저도 델파이로 프로그램을 3년전부터 하고 있지만 이런 경우는 처음이네요... 아마도... 폼이 생성되...
    • 이경모
    • 2002.09.03 00:04
    • 1 COMMENTS
    • /
    • 0 LIKES
    • 세균맨
      2002.09.03 00:19
      기본적을 원도우에서 지원하는 Port가 있읍니다.. telnet은 23 port, ftp 21 port를 사용하고 있죠. ...
    • 허진
    • 2002.09.02 23:32
    • 1 COMMENTS
    • /
    • 0 LIKES
    • 김용운
      2002.09.10 09:15
      제가 조직도 컴포넌트를 개발하고 있는데 현재는 DB에 있는 자료를 화면에 디스플레이 하는 기능과, 미리...
    • 이추형
      2002.09.03 01:35
      EInvalidOp is the exception class for undefined floating-point operations. Description : EInvali...
    • 이원상
    • 2002.09.02 23:16
    • 3 COMMENTS
    • /
    • 0 LIKES
    • 고지범
      2002.09.03 01:23
      external 이라는 키워드를 생각해보시길 바랍니다. C/C++ 과 비교해서 생각해보면 (잘 모르셔두 상관은 ...
    • 이원상
      2002.09.03 02:33
      성의 있는 답변 너무 감사합니다. 이해하는데 많은 도움이되었습니다. 그리구 동적으로 할당한 이유는 이 ...
    • 고지범
      2002.09.03 03:42
      음 지나가던 얼큰입다... ㅋㅋ 호접한 답변이 도움이 되었다니 넘 기쁩다. ^_____^ 정적할당과 동적할당...
    • 이승필
    • 2002.09.02 21:58
    • 1 COMMENTS
    • /
    • 0 LIKES
    • 한원희
      2002.09.03 06:38
      안녕하세요. 한원희입니다. TCP를 이용하시는 것이라면, 잘못된 데이터의 전송에 대한 고려를 하지 않으...