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

C++빌더 강좌/문서
C++Builder Programming Tutorial&Docments
[27] C++Builder Socket 분석 (4) - Socket에 Data가 전달될 때
정남영 [kermi] 22123 읽음    2002-04-26 03:38

4. Socket에 Data가 전달될 때

작성자 : 정남영(kermi)
E-mail : kermi@borlandforum.com 

 

0. 강의에 들어가면서

 

1. Socket Class의 구조

 

2. Socket이 접속할 때

 

3. Socket이 종료될 때

Þ

4. Socket에 Data가 전달될 때

 

5. Socket에서 Error 처리

소켓의 송, 수신에 필요한 내용을 설명하기 전 우선 TCP의 특성에 대해서 간단히 소개하고 설명을 진행하도록 하겠다.

 잘 알려진 내용이지만 TCP를 이용해서 데이터를 송, 수신할 경우에는 데이터가 신뢰성있게 도착한다는 보장은 해주지만 수신 데이터에 있어서는 좀 애매한 문제가 발생하게 된다. 그 문제는 패킷 내용이 ABCDEFG 와 123456 인 두개의 패킷을 보냈을 경우 수신 받는쪽에서도 ABCDEFG 가 도착하고 12345 가 도착하면 참 좋겠지만 ABCDEFG123 45 와 같이 도착할수도 있으며 ABCD EFG12345와 같이 도착할수도 있기 때문이다. 이런 문제는 Application에서 보정해 주어야 하며 가장 근본적인 해결책은 각 패킷의 헤더에 사이즈 정보를 담고 가는 것이다. 대부분의 네트워크 프로그램이 그렇지만 가장 단순한 형태의 프로토콜을 예로 들어보면 각 패킷은 하나의 헤더(패킷 구조 정보를 닮고 있는 부분)와 Payload(실제 정보가 담기는 부분)으로 구성되며 헤더에는 사이즈 정보 같은 실제 전송하고자 하는 내용을 표현하는데 필요한 부가적인 정보들을 담고 있으며 payload부분에는 실 정보를 담고 있게 된다.

 TCP의 특성에 대한 간략한 설명과 프로토콜 설계의 필요성에 대해서 간단히 설명하였지만 초보자에겐 아무래도 한번 예제를 보는게 낫다고 생각이 된다. 대표적인 프로토콜 구조인 HTTP같은 공개된 프로토콜의 구조도 한번씩 보면 많은 도움이 되리라 생각된다.

 이제부터 본격적인 설명을 하도록 하겠다. Borland Socket에는 데이터를 보내야 될 때 SendText와 SendBuf라는 두가지의 메소드를 제공한다. 지금까지 사용하셨던 분들은 아주 친숙하고 사용방법또한 간단한 메소드로 기억할것이다. 하지만 SendText나 SendBuf를 그대로 사용하는건 잠재적인 문제점을 가지게 된다.

 SendText나 SendBuf 메소드를 가만히 살펴보면 정수형의 return값이 돌아오는걸 알게 될것이다. 이것은 무엇을 뜻하는 것일까? 우리가 SendText나 SendBuf를 호출하면 최종적인 데이터의 송신은 Winsock API함수인 send()에 의해서 이루어지게 된다. Send()는 자신이 송신한 데이터의 길이를 return하게 된다. 만약 send함수를 이용하여 보낼려는 데이터의 길이가 100바이트 인데 send함수의 리턴값이 80이라면 20바이트가 보내지지 않은 상황이라는 것이다. 이런 경우는 어지간 해서는 발생하기 어려운 상황임엔 틀림없다. 하지만 견고한 프로그램을 위한다면 반드시 처리해 주어야 될 부분이다. 여담으로 send()함수를 호출하여 받는 리턴값이 실제로 데이터를 송신하고 리턴받는 값이라고 생각하면 안된다. Send함수의 기능은 어디까지나 Socket의 Send Buffer로 집어 넣는 걸로 끝나게 된다. 그 이후의 일은 TCP가 알아서 진행하는 부분이다.

 수신쪽에서는 ReceiveText와 ReceiveBuf라는 메소드로 받을 수가 있는데 ReceiveText야 수신된 데이터 길이를 알아서 계산해서 스트링에 넣어주지만 ReceiveBuf의 경우엔 먼저 현재 수신된 데이터의 길이를 알아내야 한다. 수신 데이터의 길이를 알아낼때는 ReceiveLength라는 멤버함수를 사용하면 현재 수신된 사이즈를 알수 있다.

 참고로 ReceiveText든 ReceiveBuf이든 한번 버퍼에서 데이터를 가지고 오면 버퍼에 있는 데이터는 삭제가 된다. 만약 버퍼에 있는 내용은 그대로 남겨두고 데이터를 가져오고 싶을때는 다음과 같이 하면 된다.

int nSize = Socket->ReceiveLength();

char *pBuffer = new char[nSize + 1];

memset(pBuffer, 0, nSize + 1);

::Recv(Socket->Handle, pBuffer, nSize, MSG_PEEK);

 

  위와 같은 작업을 하면 실제 버퍼에 있는 내용이 지워진 상태가 아니게 되며 Socket은 또다시 OnRead 이벤트를 발생하게 된다. 만약 OnRead에서 버퍼에 있는 데이터를 가져가지 않으면 무한루프를 돌듯이 계속해서 OnRead 이벤트가 발생하게 된다. 그러므로 버퍼에 있는 데이터는 즉시 가져와서 Application에 저장해서 쓰는게 좋다.

 지금까지 설명한 내용들은 극히 평범한 것일수도 있지만 견고한 프로그램을 만드는데 반드시 필요한 내용들이다. 특히 Send와 Recv에 관련된 내용들은 MSDN을 자세히 참고하여 필요한 부분들은 반드시 적용해야 한다.

 네트워크 프로그램은 디버깅하기가 일반 Application에 비해서 까다롭다. 만약 한달에 한두번꼴로 에러가 발생하는 프로그램을 디버깅한다면 엄청난 인내와 고통의 시간이 뒤따라야 될것이다. 이런 고통을 줄일수 있는 유일한 방법은 프로그램을 견고하게 만드는 것이고 철저한 테스트가 그 뒤를 따라야 한다.

 만약 네트워크를 이용한 프로그램을 자주 한다면 자신에게 필요한 라이브러리를 만들어두는걸 적극 추천하는 바이다. 여러 프로젝트를 거치면서 안전성에 대한 검증을 받기 때문에 개발 시간 단축에 큰 도움이 되리라 생각한다.

 이번 강좌도 대충 끝을 맺으려 한다. 글재주가 미천하다 보니 설명하고 싶은걸 적었다가도 말이 이상해서 뒤엎는 경우가 많아 한탄스럽기만 하다 (ㅠ.ㅠ).

 

 



+ -

관련 글 리스트
27 C++Builder Socket 분석 (4) - Socket에 Data가 전달될 때 정남영 22123 2002/04/26
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.