[네트워크] 소켓(Socket)과 포트(Port)

KimCookieYa·2023년 5월 24일
1

코딩

목록 보기
10/10

포트(Port)

  • 컴퓨터 네트워크에서 포트(Port)란, 네트워크 프로토콜에서 프로세스를 식별하기 위해 사용되는 번호이다.
  • 컴퓨터 내에서 실행 중인 여러 프로세스가 네트워크 통신을 위해 구분되는 논리적인 식별자이다.
  • 0부터 65535까지의 범위에서 사용된다.
  • HTTP 통신은 일반적으로 80번 포트를 사용하며, FTP는 21번 포트를 사용한다.
  • 포트 번호는 IP 주소와 결합하여 송신 및 수신측의 프로세스 간의 통신을 가능하게 한다.

소켓(Socket)

  • 소켈은 컴퓨터 네트워크에서 프로세스 간 통신을 가능하게 하는 추상화된 개념.
  • 리눅스 커널의 관점에서 보면, 소켓은 통신을 위한 끝점이다.
  • Unix 프로그램의 관점에서 보면, 소켓은 해당 식별자를 가지는 열린 파일이다.
  • 각 소켓은 IP 주소와 포트 번호로 이루어진 소켓 주소를 가지며, 이것은 [address: port]로 나타낸다.
  • 클라이언트의 소켓 주소 내의 포트는 클라이언트가 연결 요청을 할 때, 커널이 자동으로 할당하며, 단기(ephemeral) 포트라고 한다.
  • 반대로, 서버의 소켓 주소 내의 포트는 대개 영구적으로 이 서비스에 연결되는, 잘 알려진 포트다.(웹: 80, 이메일: 25)

소켓은 라이브러리인가? 시스템 콜인가?

소켓은 라이브러리와 시스템 콜, 두 가지 개념을 포함한다.

  1. 소켓 라이브러리: 소켓 프로그래밍을 위한 API(응용 프로그램 인터페이스)를 제공하는 라이브러리이다. 대표적인 예로는 소켓 프로그래밍을 위한 네트워크 라이브러리인 "Winsock" (Windows용)과 "BSD 소켓" (유닉스 및 유닉스 계열 운영체제용)이 있다. 소켓 라이브러리는 프로그래밍 언어별로 제공되며, 개발자는 이러한 라이브러리를 사용하여 소켓을 생성하고 관리하며, 데이터를 주고받을 수 있다.

  2. 소켓 시스템 콜: 운영체제 수준에서 소켓 기능을 제어하기 위한 시스템 콜이다. 소켓 시스템 콜은 운영체제 커널에 의해 제공되며, 네트워크 연결, 데이터 전송, 에러 처리 등과 같은 저수준의 네트워크 작업을 수행한다. 개발자는 소켓 라이브러리를 사용하여 소켓 시스템 콜을 호출하고, 운영체제의 네트워크 스택과 상호작용하여 네트워크 통신을 수행한다.

따라서, 소켓은 라이브러리와 시스템 콜의 조합으로 이루어진 개념이며, 라이브러리를 사용하여 소켓을 조작하고, 시스템 콜을 통해 운영체제의 네트워크 기능을 활용한다.

소켓 인터페이스

  • 네트워크 응용 프로그램(어플리케이션)을 만들기 위해 Unix I/O 함수들과 함께 사용되는 API(Application Programming Interface)이다.
  • 소켓 인터페이스는 응용 프로그램과 운영 체제(OS) 또는 네트워크 스택 간의 상호 작용을 추상화하여 제공한다.
  • 모든 Unix 변종, 윈도우, 메킨토시 시스템을 포함하는 대부분의 현대 시스템에서 구현되어 있다.
  • 소켓 인터페이스는 다양한 프로토콜과 통신 방식을 지원한다. TCP/IP 프로토콜 스택을 사용하는 TCP 소켓이나 UDP 소켓, RAW 소켓 등 다양한 유형의 소켓을 생성하고 제어할 수 있다.

소켓 인터페이스의 역할

클라이언트-서버 트랜잭션에서 소켓 인터페이스는 다음과 같이 동작한다.

  1. 서버 설정:

    • 서버 프로그램은 특정 포트에서 클라이언트의 연결 요청을 받기 위해 소켓을 생성하고, 해당 포트에 바인딩한다.
    • 소켓 인터페이스 함수를 사용하여 서버 소켓을 생성하고, 포트 번호를 설정하고, 바인딩한다.
    • 서버는 클라이언트의 연결 요청을 기다리며, 클라이언트와의 통신을 처리하기 위해 소켓 인터페이스 함수를 호출한다.
  2. 클라이언트 연결:

    • 클라이언트 프로그램은 서버에 연결하기 위해 소켓을 생성하고, 서버의 IP 주소와 포트 번호를 설정한다.
    • 소켓 인터페이스 함수를 사용하여 클라이언트 소켓을 생성하고, 서버의 IP 주소와 포트 번호를 설정한다.
    • 클라이언트는 서버에 연결하고, 서버와의 통신을 위해 소켓 인터페이스 함수를 호출한다.
  3. 데이터 송수신:

    • 클라이언트와 서버는 소켓 인터페이스 함수를 사용하여 데이터를 송수신한다.
    • 클라이언트는 데이터를 생성하고 서버로 데이터를 전송하기 위해 send() 함수를 사용한다.
    • 서버는 recv() 함수를 사용하여 클라이언트로부터 데이터를 수신한다.
    • 서버는 수신한 데이터를 처리하고, 필요에 따라 클라이언트로 응답 데이터를 생성하여 send() 함수를 사용하여 클라이언트에게 전송한다.
    • 클라이언트는 recv() 함수를 사용하여 서버로부터 응답 데이터를 수신한다.
  4. 연결 종료:

    • 클라이언트나 서버는 데이터 통신을 마치면 소켓을 닫아 연결을 종료한다.
    • close() 함수를 사용하여 소켓을 닫고, 연결을 종료한다.

위의 개요를 통해 클라이언트와 서버는 소켓 인터페이스 함수를 호출하여 네트워크를 통해 효율적인 통신을 수행할 수 있다.

예제 코드

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 12345

int main() {
    int client_socket;
    struct sockaddr_in server_address;
    char server_message[256];
    
    // 클라이언트 소켓 생성
    client_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (client_socket < 0) {
        perror("소켓 생성 실패");
        exit(EXIT_FAILURE);
    }
    
    // 서버 주소 설정
    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(SERVER_PORT);
    if (inet_pton(AF_INET, SERVER_IP, &(server_address.sin_addr)) <= 0) {
        perror("잘못된 서버 주소");
        exit(EXIT_FAILURE);
    }
    
    // 서버에 연결
    if (connect(client_socket, (struct sockaddr *)&server_address, sizeof(server_address)) < 0) {
        perror("서버 연결 실패");
        exit(EXIT_FAILURE);
    }
    
    // 서버로 데이터 전송
    strcpy(server_message, "Hello, server!");
    if (send(client_socket, server_message, strlen(server_message), 0) < 0) {
        perror("데이터 전송 실패");
        exit(EXIT_FAILURE);
    }
    
    // 서버로부터 데이터 수신
    memset(server_message, 0, sizeof(server_message));
    if (recv(client_socket, server_message, sizeof(server_message), 0) < 0) {
        perror("데이터 수신 실패");
        exit(EXIT_FAILURE);
    }
    
    printf("Received: %s\n", server_message);
    
    // 소켓 연결 종료
    close(client_socket);
    
    return 0;
}

소켓 구조체 in C언어

#include <sys/socket.h>

struct sockaddr {
    unsigned short sa_family;   // 주소 패밀리 (Address Family)
    char sa_data[14];           // 주소 데이터
};

struct sockaddr_in {
    short sin_family;           // 주소 패밀리 (Address Family)
    unsigned short sin_port;    // 포트 번호
    struct in_addr sin_addr;    // IP 주소
    char sin_zero[8];           // 사용되지 않음
};

struct in_addr {
    unsigned long s_addr;       // 32비트 IP 주소
};

위의 구조체는 소켓 프로그래밍에서 주로 사용되는 구조체 중 일부이다. struct sockaddr는 일반적인 소켓 주소를 나타내며, struct sockaddr_in은 IPv4 주소와 포트 번호를 포함하는 소켓 주소를 나타낸다. struct in_addr는 32비트의 IPv4 주소를 나타내는 데 사용된다.

profile
[크래프톤 정글 2기], 티스토리로 이주했습니다:)

3개의 댓글

comment-user-thumbnail
2023년 12월 12일

안녕하세요 2기 수료자님 취업하셨나요??

1개의 답글