본문 바로가기

컴퓨터 네트워크

컴퓨터 네트워크 : Chapter 2. 소켓의 타입과 프로토콜의 설정

2. 1 소켓의 프로토콜과 그에 따른 데이터 전송 특성

1) 프로토콜의 이해와 소켓의 생성

  • 프로토콜이란
    • 개념적으로 약속의 의미를 담고 있다.
    • 컴퓨터 상호간의 데이터 송수신에 필요한 통신규약
    • 소켓을 생성할 때 기본적인 프로토콜을 지정해야한다.
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
→ 성공 시 파일 디스크립터, 실패 시 -1 반환
// domain : 소켓이 사용할 프로토콜 체계(Protocol Family) 정보 전달
// type : 소켓의 데이터 전송방식에 대한 정보 전달
// protocol : 두 컴퓨터 간 통신에 사용되는 프로토콜 정보 전달
매개 변수 domain, type 및 protocol은 모두 프로토콜 정보와 관련이 있음

2) 프로토콜 체계(Protocol Family)

  • 프로토콜 체계
    • 프로토콜도 그 종류에 따라서 부류가 나뉘는데, 그 부류를 가리켜 프로토콜 체계라고 한다.
    • 프로토콜의 체계 PF_INETIPv4 인터넷 프로토콜 체계를 의미
      → 이를 기반으로 소켓 프로그래밍을 할 것임!!

대표적인 프로토콜 체계 정보

3) 소켓의 타입(Type)

  • 소켓의 타입
    • 데이터 전송방식을 의미
    • 소켓이 생성될 때 소켓의 타입도 결정되어야 한다
  • 프로토콜 체계 PF_INET의 대표적인 소켓 타입 둘
    • 연결 지향형 소켓 타입(TCP)
    • 비 연결 지향형 소켓 타입(UDP)

(1) 연결지향형 소켓(SOCK_STREAM)의 데이터 전송 특성

  • 중간에 데이터 소멸되지 않음 → TCP는 소멸되도 재전송하기 때문에
  • 전송 순서대로 데이터가 수신됨
  • 데이터의 경계가 존재하지 않음
  • 소켓 대 소켓의 연결은 반드시 1 대 1의 구조

(2) 비 연결지향형 소켓(SOCK_DGRAM)의 데이터 전송 특성

  • 전송순서 상관없이 빠른 속도의 전송을 지향 → 경우에 따라 TCP가 더 빠른 경우가 있어서 애매한 특성
  • 데이터 손실 및 파손의 우려 있음 → 문제 발생 시 Application에서 해결해야 함
  • 데이터 경계가 존재 → Application 입장에서 존재
  • 한번에 전송할 수있는 데이터의 크기가 제

4) 프로토콜의 최종선택

// IPv4 인터넷 프로토콜 체계에서 동작하는 연결지향형 데이터 전송 소켓(TCP)
int tcp_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

// IPv4 인터넷 프로토콜 체계에서 동작하는 비연결지향형 데이터 전송 소켓(UDP)
int udp_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
첫번째, 두번째 인자로 전달된 정보를 통해서 소켓의 프로토콜이 사실상 결정되기 때문에 세 번째 인자로 0을 전달해도 됨

5) 연결지향형 소켓! TCP 소켓의 예

  • 전송되는 데이터의 경계(boundary)가 존재하지 않음을 확인

<서버>

if(bind(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1)
	error_handling("bind() error");
    
if(listen(serv_sock, 5) == -1)
	error_handling("listen() error");
clnt_addr_size = sizeof(clnt_addr);
clnt_sock = accept(serv_sock, (struct sockaddr*) &clnt_addr, &clnt_addr_size);
if(clnt_sock = -1)
	error_handling("accept() error");
write(clnt_sock, message, sizeof(message));  // tcp_Server.c의 데이터 전송
close(clnt_sock);
close(Serv_sock);

<클라이언트>

if(connect(sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1)
	error_handling("connect() error!");
while(read_len = read(sock, &message[idx++], 1)) // tcp_client.c의 데이터 수신
{
	if(read_len == -1)
    {
    	error_handling("read() error!");
        break;
    }
    str_len += read_len;
}
printf("Message from server: %s \n", message);
printf("Function read call count: %d \n", str_len);
<클라이언트 데이터 수신>
application에서는 하나의 데이터로 전달하지만 네트워크(TCP)에서는 application에서 경계에 상관없이 임의의 크기대로 나눠서 보낸다. 그리고 수신자는 통째로 받기 때문에 한 바이트씩 읽어야 함
→ 보낼 때는 하나를 보냈지만 받을 때는 경계가 존재하지 않기 때문에 한 바이트씩 받는 것!!
소켓에서 한 바이트(한 문자)씩 받아서 읽어 온다.