C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 팁&트릭
C++Builder Programming Tip&Tricks
[222] 소켓통신시 데이터 짤리는 문제에 관한 몇가지 해결방법
나그네 [] 8701 읽음    2001-11-29 09:14

프로그램을 하다가 우연히 발견한 겁니다. 물론 이미 알고 계신분들도 있으리라
생각합니다만 정보공유 차원에서 몇자 적습니다.

보통 TCP/IP를 이용한 프로그램을 작성하다보면 예기치 않은 문제점들이 나옵니다.
메뉴얼에도 거의 언급을 하지않은 문제들때문에 많은 고생을 하는경우도 생깁니다.
제가 겪은 문제도 이와 비슷한겁니다.
문제는 바로 send ()라는 함수에서 비롯되었습니다.
분명히 절차에 맞추어서 SERVER쪽에서는 socket을 만들고 accept까지 합니다.
그리고 CLIENT를 제작하고 양쪽에 필요한 프로토콜을 정의한다음 통신을 시도하면
잘됩니다.
문제는 TEST이외에 실전에서 발생할때가 많죠.
저도 처음접한 문제는 분명 1M상당의 데이터를 보냈는데 받는쪽에서는 무슨이유인지

중간에짤리고 NULL이 들어가고... 즉 오염된 DATA를 받게된다는 거지요.
그래서 이책 저책을 뒤져봐도 아무이야기없고...
결국은 근처 경험많은 분에게 도움을 요청해서 겨우 원인을 알아냈습니다.
그때당시 사용기종은 DIGITAL ALPHA SERVER를 사용하였습니다.
문제는 내부 버퍼의 크기문제였죠. 물론 이것을 안후에 데이타를 볼낼때는 512BYTES

씩 끊어서 보내게했죠. 결과는 안전하게 모든 데이터가 도착을 했더군요.
하지만 이후에 다른 프로젝트를 맡게 되었고 같은문제를 만났는데 이건 도저히 답이

없더군요.
분명 1024 또는 512로 데이터를 나누어서 보냈는데 받는 쪽놈이 어떨때는 받고 어떨

때는 안받고 하더군요...
이건 어쩔도리가 없었는데 우연히 근처 동료분이 문의를 해왔습니다.
DEBUG를 위해서 printf를 넣을때는 확실히 잘가는데 printf를 빼니까 데이타가
깨져가더라. 해결책은 없나?
곰곰히 생각해봤죠. 물론 KERNEL까지 생각하지 않아도 결론은 하나였죠.
그래서 동료분에게 printf대신에 fflush (stdout)을 넣으라고 했죠. 결과는 무사히
데이터가 전달된다고 하더군요.
제가 맞고 있는 부분에서도 테스트를 해보았죠.(동료는 UNIX에서 작업을 했었고 저
는 Windows-9x에서 작업했죠.) 저역시 잘되더군요.

왜 이렇게 되었을까요?
첫번째 내부 버퍼의 크기는 OS를 작성하는 곳마다 다릅니다. 외부에서 이버퍼를
조작하게 할 수도 있고(DEC OS의 경우) KERNEL에서 조정을 해주어야 하는 경우도
(LINUX의 경우)있습니다. 하지만 이렇게 시스템적인 것을 조정하는 것 보다는 자신
의 응용프로그램에서 미리 적당히 (1024나 512로) 잘라서 보내주는 것이 좀더 안전
한방법입니다.
두번째 경우도 내부 버퍼와 관련있는 것입니다. UNIX에서는 모든 것이 함수 형태로
되어있고 멀티 유저를 지원합니다. 따라서 동시에 여러사람이 작업을 할때 그 순서
를 정하고 실행하게 해주는 역할을 합니다. 이때 내부버퍼는 공용중요한 역할을 합
니다. 즉, 쓰기작업을 하다가 자신에게 주어진 시간이 다되었다면? 현재까지 작업
한것을 그대로 쓸까요? 아니면 다음에 명령을 기다릴까요? 멀티유저를 지원하는 OS
라면 당연히 기다립니다. 여러가지 이유가 있습니다면 여기서는 논외이므로...
하여간 이렇게 출력을 기다리게 만들어진 부분은 때로는 프로그래머를 당황하게 만
들기도 합니다. 즉, 위에서와 같은 일이발생하여 보내기로 했는데 보내지지 않았다
면 큰일 아닙니까? 그래서 만들어낸것이 fflush (File Flush - 즉, 파일을 깨끗이
한다...)라는 것입니다. 이 fflush의 작동은 지정한 파일포인터의 버퍼를 깨끗이
해주는 즉, 쓰기작업이 있었다면 지금시점에서 쓰기를 강요하는 함수입니다.
위에서 stdout이라고 썼는데 이것은 '표준출력'을 나타냅니다. send로 보내지는
데이터는 표준 출력을 이용한다고 생각하시면됩니다. 따라서 이 데이터를 보내고
이 표준출력버퍼를 비우라고 한다면 시스템에서는 안보내는 일이 없겠죠?

위에서 서술한 이야기의 요점입니다.
1. 소켓 통신을 할때 보내는 측의 데이터는 짤라서 보내라.(1024나 512로)
   물론 받는 측에서도 그 크기만큼씩받아서 모으면 되겠죠?
   크기를 주고받는부분은 프로토콜에서 정의하면 되겠죠?
2. 정확한 보내기를 하기위해서는 fflush (stdout)을 send함수 바로 다음에
   실행 시켜라.

두가지 입니다.
혹 이러한 이유로 고생하고 계시는 분들을 위해 잘쓰지도 못하는 글을 적어봅니다.

+ -

관련 글 리스트
222 소켓통신시 데이터 짤리는 문제에 관한 몇가지 해결방법 나그네 8701 2001/11/29
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.