Justweon
Justweon
Justweon
전체 방문자
오늘
어제
  • 분류 전체보기 (76)
    • 웹 개발 (4)
      • React (2)
      • Spring (0)
    • 모바일 앱 프로그래밍 (4)
    • 네트워크 프로그래밍 (17)
      • C (17)
    • DATA (42)
      • 데이터 사이언스 (6)
      • 머신 러닝 (31)
      • 데이터베이스 (2)
      • 기타 (3)
    • 토이 프로젝트 (3)
      • 닮은 배우 분류기 (2)
      • PDF 변환기 (GUI) (1)
    • 취미 (2)
      • Photoshop (1)
      • 먹부림 (1)
    • 이것저것 (2)
    • 보안 (1)
      • 드림핵 (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • pandas
  • 모델 평가
  • 알고리즘
  • 분류
  • 프로젝트
  • SVM
  • 과소적합(underfitting)
  • 정규화
  • 그리드 서치
  • 데이터 전처리
  • 데이터 사이언스
  • GUI
  • 취미
  • 샐러드
  • MLP
  • 시각화
  • 텐서보드
  • 맛집
  • 머신 러닝
  • 하이퍼파라미터
  • tensorflow
  • 과대적합(overfitting)
  • 심층 신경망
  • 하이퍼 파라미터
  • 경사 하강법
  • keras
  • 콜백
  • 코랩
  • 파이썬
  • 토이프로젝트

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Justweon

Justweon

네트워크 프로그래밍/C

[네트워크 프로그래밍/C] 소켓의 프로토콜과 그에 따른 데이터 전송 특성

2022. 2. 17. 15:14

프로토콜이란?

멀리 떨어진 두 사람이 대화를 하기 위해서는 나름의 대화방법을 정해야 합니다. 한 사람은 전화로 하고 한 사람은 편지로 대화를 시도한다면 대화가 똑바로 이루어질 리가 없겠죠. 따라서 이 두 사람이 전화로 대화를 하기로 결정하였다면 이 두사람이 대화에 사용한 프로토콜은 전화라고 얘기할 수 있습니다. 이렇듯 프로토콜은 대화에 필요한 통신규약입니다. 컴퓨터의 관점에서 얘기하면 프로토콜은 컴퓨터 상호간의 대화에 필요한 통신규약이라고 할 수 있습니다.

소켓의 생성

앞서 포스팅한 글에서는 소켓과 관련된 함수를 사용하는 코드만 보고 넘어갔었는데, 각 함수에 대해 자세히 설명해보도록 하겠습니다. 아래 함수는 소켓을 생성하는 데 사용하는 함수이고, 전달해야 하는 인자는 다음과 같습니다.

  • int domain: 소켓에 사용할 프로토콜 체계(Protocol Family) 전달
  • int type: 소켓의 데이터 전송방식에 대한 정보 전달
  • int protocol: 두 컴퓨터간 통신에 사용되는 프로토콜 정보 전달
// 성공 시 파일 디스크립터, 실패 시 -1 반환
#include <sys/socket.h>

int socket(int domain, int type, int protocol);

프로토콜 체계(Protocol Family)

소켓이 통신에 사용하는 프로토콜에는 여러 종류들이 있습니다. 그리고 위에서 봤듯이 소켓을 생성할 때 첫 번째 인자로 소켓이 사용할 프로토콜의 부류정보를 전달해야 합니다. 이러한 부류정보를 가리켜서 프로토콜 체계라고 하며, 그 종류는 다음과 같습니다.

이름 프로토콜 체계(Protocol Family)
PF_INET     IPv4 인터넷 프로토콜 체계
PF_INET6     IPv6 인터넷 프로토콜 체계
PF_LOCAL     로컬 통신을 위한 UNIX 프로토콜 체계
PF_PACKET     Low Level 소켓을 위한 프로토콜 체계
PF_IPX     IPX 노벨 프로토콜 체계

위 표에서 보이는 PF_INET에 해당하는 IPv4 인터넷 프로토콜 체계가 앞으로 포스트에서 주로 다루게 될 프로토콜 체계입니다. 이외에도 몇몇 프로토콜 체계들이 존재하지만, 중요도가 떨어지거나 보편화되지 않았으므로 주로 PF_INET 프로토콜 체계에 맞춰서 설명을 하겠습니다.

소켓의 타입

소켓의 타입이란 소켓의 데이터 전송방식을 뜻합니다. 이 정보를 socket 함수의 두번째 인자로 전달해야 합니다.

그런데 위에서 프로토콜 체계를 정해줬는데 데이터 전송방식을 또 정해줘야하나..싶을 수도 있는데, 프로토콜 체계가 정해졌다고 해서 데이터 전송방식까지 정해지는 것은 아닙니다. 주로 사용할 PF_INET 프로토콜 체계에도 둘 이상의 데이터 전송방식이 존재합니다. 대표적인 두 가지 데이터 전송방식을 살펴보겠습니다.

소켓의 타입 1: 연결지향형 소켓(SOCK_STREAM)

socket 함수의 두 번째 인자로 SOCK_STREAM을 전달하면 연결지향형 소켓이 만들어집니다. 연결지향형 소켓은 다음과 같은 특징들을 지닙니다.

  • 소켓 대 소켓의 연결은 반드시 1대 1
  • 중간에 데이터가 소멸되지 않고 목적지로 전송
  • 전송 순서대로 데이터 수신
  • 전송되는 데이터의 경계가 존재하지 않음

마지막 특징에 전송되는 데이터의 경계가 존재하지 않는다는 말이 무슨 말인지 이해가 안될 수도 있을 것 같아 부연설명을 하겠습니다. 데이터를 전송하는 컴퓨터가 데이터를 세 묶음을 보냈지만, 데이터를 수신하는 컴퓨터는 이를 한 묶음으로 처리할 수도 있다는 말입니다. 다시말하면, read 함수와 write 함수의 호출 횟수가 연결지향형 소켓에서는 큰 의미를 갖지 못한다고 말할 수 있습니다.

소켓의 타입2: 비 연결지향형 소켓(SOCK_DGRAM)

socket 함수의 두 번째 인자로 SOCK_DGRAM을 전달하면 비 연결지향형 소켓이 생성됩니다. 이 소켓은 다음과 같은 특징들을 지닙니다.

  • 전송된 순서에 상관없이 가장 빠른 전송을 지향
  • 전송된 데이터는 손실의 우려가 있고, 파손의 우려가 있음
  • 전송되는 데이터의 경계가 존재
  • 한 번에 전송할 수 있는 데이터의 크기가 제한

이번에는 연결지향형 소켓과는 다르게 전송되는 데이터의 경계가 존재합니다. 비 연결지향형 소켓에서는 데이터를 택배로 이해하면 편합니다. 택배상자가 두 개인데, 이를 세 번에 걸쳐서 나눠받을 수는 없습니다. 다시말하면, 비 연결지향형 소켓에서는 read 함수의 호출 횟수와 write함수의 호출 횟수가 같아야 합니다.

프로토콜의 최종선택

이제 socket 함수의 세 번째 인자에 대해 살펴볼 차례입니다. socket 함수의 첫 번째, 두 번째 인자를 통해서도 충분히 원하는 유형의 소켓을 만들 수 있습니다. 따라서 대부분의 경우 세 번째 인자로 그냥 0을 넘겨줘도 우리가 원하는 소켓을 생성할 수 있습니다. 하지만 하나의 프로토콜 체계 안에 데이터의 전송방식이 동일한 프로토콜이 둘 이상 존재하는 상황 때문에 세 번째 인자가 필요합니다.

 

예를 두 가지 들어보겠습니다.

IPv4 인터넷 프로토콜 체계(PF_INET)에서 동작하는 연결지향형 데이터 전송 소켓(SOCK_STREAM)을 만든다고 할 때, 이 두 가지 조건을 만족시키는 프로토콜은 IPPROTO_TCP 하나이기 때문에 다음과 같이 소켓 호출문을 구성할 수 있습니다. 그리고 이 때 생성되는 소켓을 가리켜 TCP 소켓이라고 합니다.

socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

 그리고 IPv4 인터넷 프로토콜 체계(PF_INET)에서 동작하는 비 연결지향형 데이터 전송 소켓(SOCK_DGRAM)을 만든다고 할 때, 이 두 조건을 만족하는 프로토콜은 IPPROTO_UDP 하나이기 때문에 다음과 같이 소켓 호출문을 구성할 수 있습니다. 그리고 이 때 생성되는 소켓을 가리켜 UDP 소켓이라고 하겠습니다.

socket(PF_INET, SOCK_STREAM, IPPROTO_UDP);

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

마지막으로 연결지향형 소켓인 TCP 소켓의 예를 살펴보고 이번 포스트를 마무리하겠습니다. 앞서 이 글에서 다뤘던 Hello world! 서버 프로그램을 그대로 사용하고, 클라이언트 소스를 조금 변경해서 TCP 소켓의 전송되는 데이터의 경계가 존재하지 않는 특성을 확인해보겠습니다.

/*
서버 프로그램으로는 hello_server.c를 이용합니다.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

void error_handling(char* message);

int main(int argc, char* argv[]) {
    int sock;
    struct sockaddr_in serv_addr;
    char message[30];
    int str_len = 0;
    int idx = 0, read_len = 0;

    if (argc != 3) {
        printf("Usage : %s <IP> <port>\n", argv[0]);
        exit(1);
    }

    // 소켓 생성
    sock = socket(PF_INET, SOCK_STREAM, 0);
    if (sock == -1)
        error_handling("socket() error");

    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
    serv_addr.sin_port = htons(atoi(argv[2]));

    // connect 함수호출로 서버 프로그램에 연결 요청
    if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1)
        error_handling("connect() error");

    // hello_client와 달라진 부분.
    // TCP 소켓의 특성을 확인하기 위하여 read를 여러번 호출해서 데이터를 수신
    while (read_len = read(sock, &message[idx++], 1)) {
        if (read_len == -1)
            error_handling("read() error");
        str_len += read_len;
    }
    
    printf("Message from server : %s\n", message);
    printf("Function read call count: %d\n", str_len);
    close(sock);
    return 0;
}

void error_handling(char* message) {
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

결과는 아래와 같습니다.

TCP 소켓 특성 확인을 위한 예제 결과

'네트워크 프로그래밍 > C' 카테고리의 다른 글

[네트워크 프로그래밍/C] 네트워크 바이트 순서와 인터넷 주소 변환  (0) 2022.02.21
[네트워크 프로그래밍/C] 주소정보의 표현  (0) 2022.02.17
[네트워크 프로그래밍/C] 소켓에 할당되는 IP주소와 PORT 번호  (0) 2022.02.17
[네트워크 프로그래밍/C] 리눅스 기반 파일 조작하기  (0) 2022.02.16
[네트워크 프로그래밍/C] 네트워크 프로그래밍과 소켓의 이해  (0) 2022.02.16
    '네트워크 프로그래밍/C' 카테고리의 다른 글
    • [네트워크 프로그래밍/C] 주소정보의 표현
    • [네트워크 프로그래밍/C] 소켓에 할당되는 IP주소와 PORT 번호
    • [네트워크 프로그래밍/C] 리눅스 기반 파일 조작하기
    • [네트워크 프로그래밍/C] 네트워크 프로그래밍과 소켓의 이해
    Justweon
    Justweon
    공부 목적을 위해 기록하는 블로그입니다 :)

    티스토리툴바