본문 바로가기

ComputerScience/Network

[Network] 프로토콜 표준과는 다르게 실제로는 소켓(Socket)이 어떻게 식별되는가?

네트워크 프로그래밍에서 Socket의 의미와 TCP/IP Stack에 대하여

이미지 출처: https://www.guru99.com/images/1/093019_0615_TCPIPModelW1.png

  • TCP/IP 스택은 프로토콜 스택으로, 컴퓨터 시스템의 관점에서 어플리케이션이 사용할 수 있는 네트워크 기능을 지원하는 역할을 한다.
  • TCP/IP 스택은 전체를 4개의 레이어로 이루어진 시스템(Transport + Internet + Network Interface)에 제공되는 네트워크 기능의 구현과 Application 레벨에서 구현된 네트워크 기능으로 구분된다.
  • 네트워크 통신을 위해서는 Application 레이어에서 통신이 가능하도록 System 레벨에서 지원되어야 한다는 것이 중요하다.

Socket Programming

  • 어플리케이션이 운영체제의 기능, 즉 커널 코드나 시스템 코드에 바로 접근하여 사용하는 것이 불가능하다.
  • 시스템은 어플리케이션이 사용할 수 있는 인터페이스를 제공해야 하고, 네트워크 기능을 사용하고 싶다면 Socket을 통해서만 사용이 가능하다.
  • Socket 프로그래밍을 통해, 어플리케이션이 네트워크를 통해 다른 프로세스와 데이터를 주고 받을 수 있다.
  • Socket프로그래밍은 어플리케이션 개발자들이 Socket 인터페이스를 호출할 수 있도록 하는 프로그래밍 방식이다.
  • 따라서, 어플리케이션을 구현하는 개발자들은 Socket 프로그래밍을 사용하여 네트워크에서 데이터 주고받기를 구현할 수 있다.

Socket

  • 소켓은 컴퓨터 시스템이 제공하는 인터페이스로, 어플리케이션 개발자가 네트워크 상에서 데이터를 주고받을 수 있도록 도와준다.
  • 일반적으로 개발자가 소켓을 직접 조작하여 통신 기능을 구현하는 것은 적으며, 대부분은 라이브러리나 모듈을 통해 구현된다.
  • 라이브러리나 모듈을 열어보면 소켓을 활용해서 프로토콜을 구현했음을 알 수 있다.
  • 네트워크 통신 기능은 소켓을 활용하는데, 프로토콜 표준에 따라 소켓의 동작이 정의되며, 운영체제마다 소켓 형태로 네트워크 기능을 제공한다.

Socket 생성, 프로토콜 설정, 주소 할당 과정

  • 소켓 프로그래밍에서 프로토콜과 IP 주소, 포트 넘버를 할당하여 소켓을 생성한다. <protocol, IP address, port number>
  • 포트 넘버는 서버 측에서 반드시 명시를 해주어야 클라이언트 측에서도 해당 포트 넘버로 데이터를 보낼 수 있다.
  • 클라이언트 측에서는 주소를 바인딩할 필요가 없어 OS가 자동으로 할당한다.
import socket

# 서버 소켓 생성
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 서버 주소 및 포트 설정
server_address = ('localhost', 8080)

# 서버 소켓 바인딩
server_socket.bind(server_address)

# 서버 소켓 리슨 시작
server_socket.listen()

# 클라이언트 연결 수락
client_socket, client_address = server_socket.accept()

# 클라이언트로부터 데이터 수신
data = client_socket.recv(1024)

위 코드에서 SOCK_STREAM은 프로토콜이며, server_socket.bind(server_address) 를 통해 IP와 Port number를 정의한다.

실제 구현에서 프로토콜과 IP Address, Port number를 통해 소켓을 유니크하게 식별할 수 있을까?

  • 실제 구현에서 UDP의 경우 IP Address, Port로 유니크하게 식별 가능하지만, TCP의 경우 IP와 포트 넘버로는 유니크하게 식별할 수 없다.
  • TCP 소켓은 Connection을 맺기 위해 클라이언트가 서버로 요청을 보내야하며, 서버는 항상 요청을 기다리는 소켓이 필요하다.

️TCP Connection에서 소켓 식별 과정

  • TCP Connection은 3-way hand shake를 통해 성립된다.
  • 클라이언트와 서버는 각각 소켓을 만들어 커넥션을 맺는다.
  • Connection이 맺어지면, 이후 데이터를 주고받기 위해 새로운 소켓을 만들어 사용한다.
  • 이 때 서버쪽에서 모든 소켓은 같은 IP 주소와 포트를 가지고 있음.
  • 이 경우, 어떤 소켓으로 데이터를 보내야 하는지 알 수 없으므로 Connection을 맺기 전에는 Listening 소켓으로 보내며, 맺은 후에는 src IP, src port 정보를 확인하여 적절한 소켓으로 전달함.

TCP 스펙에 따라 IP 주소와 Port number가 중복될 때 문제점

  • 클라이언트 소켓이 주소를 찾아주는데, 그 주소 할당 방식은 OS가 이전에 사용되지 않은 포트 넘버를 할당한다.
  • 그러나 이미 모든 포트 번호가 사용중인 경우, 동일한 IP 주소와 포트 번호를 가진 서로 다른 소켓이 생성될 수 있으나, TCP 스펙상 이는 허용되지 않는다.
  • 한 IP 주소와 포트 넘버를 가진 커넥션이 이미 존재하는 경우, TCP 스펙상 유니크한 값이 아니므로 해당 소켓이 다시 연결을 맺을 수 없다.
  • 따라서, 모든 커넥션은 포트와 IP 주소 값이 다르게 유니크해야 한다는 조건 때문에 같은 IP 주소와 포트 넘버를 가지고 있는 소켓이 추가 연결을 맺는 것이 불가능하다.

UDP Socket의 동작

  • TCP는 IP 프로토콜 위에서 동작하고 안정적으로 데이터를 전송하기 위해 Connection 기반으로 동작한다.
  • UDP는 IP 주소와 Port number로 소켓을 식별하며, Connection 개념이 없다. 
  • UDP는 데이터 손실이나 데이터 순서 변경 등의 불안정한 프로토콜로 동작한다.
  • UDP 소켓에서 데이터를 보낼 때마다 해당 UDP 소켓 주소를 지정하여 데이터를 전송하고, 받는 쪽에서도 해당 소켓 주소를 확인하여 데이터를 읽는다.

Port number

  • 포트 번호(Port number)는 16비트로 이루어지며, 0에서부터 65,535까지 사용 가능하다.
  • 포트 번호는 크게 3가지로 나뉘는데, 0 ~ 1023번은 Well known, System 포트 e.g.) HTTP(80), HTTPS(443), DNS(53), 1024 ~ 49151은 registered 포트(IANA에 등록된 포트) e.g.) MySQL DB(3306), Apache Tomcat(8080), 그리고 나머지는 Dynamic 포트이다.
  • 등록 포트는 IANA(인터넷 할당 번호 관리 기관)에서 번호가 등록되어 있는 포트를 의미하는데, MySQL을 위한 3306번, 아파치 웹 서버의 기본 포트 80 등등이 이에 속한다.

참고 자료

https://youtu.be/WwseO8l8rZc?si=tR33YDUZTjKBYXl2