윈도우 소켓 프로그래밍(TCP)

카테고리 없음 2014. 2. 5. 07:35

소켓을 생성할때는 라이브러리에서 제공하는 소켓생성 구조체를 사용합니다. SOCKET 구조체는 주소,

소켓타입 프로토콜 등을 사용자가 직접 지정해 주어야 합니다.

 

생성후 사용자가 요청한 프로토콜을 이용하여 통신할수 있도록 내부적으로 리소스를 할당해, 접근시 핸들값

(SOCKET 타입, 32비트 정수)의 디스크립터를 리턴합니다. 프로토콜시 자주 이용하는 것은 TCP, UDP입니다.(AF_INET)

 

소켓통신이 끝나면 리소스를 반환해야 합니다. 쉽게 말하면 메모리를 할당한뒤 free하는것가 같습니다.

소켓 리소스 제거는 closesocket() 를 사용해 소켓 리소스를 제거합니다.


TCP서버, 클라이언트는 다음과 같은 순서로 소켓 함수를 호출합니다.

클라이언트는 서버와 달리 bind()함수를 호출하지 않습니다. Bind()함수 없이 connect()함수를 호출하면

OS는 자동적으로 지역 IP주소와 포트번호를 설정합니다.

 

- Socket : 소켓생성

- Connect() : 서버에 접속 요청

- Send(), recv() : 데이터 전송, 수신 함수로 서버/클라이언트 와 통신을 수행합니다.

- Closesocket() : 소켓을 종료합니다.

 

Connect()함수는 서버에게 접속하여 TCP 프로토콜 수준의 연결을 설정합니다.

s: 서버와 통신하기 위해 만든 소켓, name : 서버 주소를 초기화 한 소켓 구조체 변수의 주소값

 namelen : 소켓 구조체 변수의 길이



SOCKADDR_IN serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr("128, 0, 0, 1");
int retval = connect(sock, (SOCKADDR*)&serveraddr, sizeof(serveraddr));
if(retval == SOCKET_ERROR)
err_quit("connect()");

데이터 전송은 Send()함수를 이용합니다.

데이터를 송신 버퍼에 복사함으로 프로토콜에 의해 데이터가 전송 되도록 합니다.

 s : 통신할 대상과 연결된 소켓, buf : 보낼 데이터를 담고 있는 어플리케이션 버퍼의 주소

 len : 보낼 데이터 크기, Flags : send() 함수의 동작을 바꾸는 옵션(대부분 0을 사용)

 

데이터 수신 함수는 recv()함수를 사용합니다.

수신 버퍼에 도착한 데이터를 어플리케이션의 버퍼로 복사합니다.

s : 통신할 대상과 연결된 소켓, buf : 받은 데이터를 저장할 어플리케이션 버퍼의 주소, len : 수신 버퍼로 부터 복사할 최대 크기

 flags : recv()함수의 동작을 바꾸는 옵션(대부분 0을 사용)

recv()함수 사용시 주의점은 TCP메시지 경계를 구분하지 않기 때문에, 세번째 인자인 len으로 지정한 크기보다

작은 데이터가 어플리케이션 버퍼로 복사될수 있습니다. 따라서 자신이 받을 데이터의 크기를 알고 있다면,

해당 크기만큼 받을때 recv() 함수를 여러번 호출해야 합니다.

 

어플리케이션 프로토콜과의 메세지 설계를 할때 경계 구분 세가지 방법을 소개합니다.

송신자 입장에서는

1. 항상 고정길이 데이터를 보냄

2. 경계 구분을 위해 특별한 표시(eor : End of Record)

3. 보낼 데이터 길이를 고정 길이 데이터로 보낸후, 가변 길이 데이터를 이어서 송신(헤더 추가)

 

수신자 입장에서는

1. 항상 고정 길이 데이터를 수신

2. EOR이 나올때 까지 데이터를 읽은 후 처리

3. 고정 길이 데이터를 읽어 뒤 따라올 데이터의 길이를 알아냄, 이 길이만큼 데이터를 읽어 처리(헤더를 읽고 처리)

가장 많이 사용되는 방법은 3번 입니다.