에듀테크 프로젝트 대시보드
포트 번호와 소켓
IP 주소는 이 컴퓨터까지만 데이터를 데려다준다. 그런데 컴퓨터 안에는 브라우저도, 게임도, 메신저도 동시에 켜져 있다. 도착한 데이터를 어느 프로그램에게 줄지는 누가, 어떻게 정할까?
내 컴퓨터의 IP 주소가 192.168.0.12라고 하자. 지금 이 컴퓨터에서는
동시에 여러 프로그램이 인터넷과 통신 중이다.
offset0xf.com을 보는 중이때 192.168.0.12로 데이터 패킷 하나가 도착했다. IP 헤더에는
"목적지 IP = 192.168.0.12" 라고만 적혀 있을 뿐, 어느 프로그램에게 전달해야 하는지는
전혀 적혀 있지 않다. IP는 딱 여기, 호스트(컴퓨터)까지만 책임지는 주소 체계이기 때문이다.
이 문제를 해결하는 것이 바로 전송 계층(4계층)의 포트 번호다.
포트 번호는 0 ~ 65535 범위의 숫자로, 한 컴퓨터 안에서 어느 프로그램(서비스)이 이 데이터를 받을지 구분하는 이름표다. 흔히 이렇게 비유한다.
동 번호 — 어느 건물인지
호 번호 — 건물 안 어느 집인지
클라이언트가 서버에 접속하려면 "어느 포트로 가야 하는지" 미리 약속돼 있어야 한다.
그래서 자주 쓰이는 서비스들은 전 세계가 합의한 고정 번호를 쓴다. 브라우저 주소창에
포트를 안 적어도 https://면 자동으로 443번으로 가는 이유가 바로 이것이다.
| 포트 | 프로토콜/서비스 | 용도 |
|---|---|---|
| 20/21 | FTP | 파일 전송 (데이터/제어) |
| 22 | SSH | 원격 서버 접속·터미널 |
| 25 | SMTP | 이메일 발송 |
| 53 | DNS | 도메인 이름 → IP 주소 조회 |
| 80 | HTTP | 일반 웹사이트 접속 |
| 443 | HTTPS | 암호화된 웹사이트 접속 |
브라우저가 웹서버 443번 포트에 접속할 때, 내 컴퓨터 쪽에서도 포트가 하나 필요하다.
이때 OS가 동적 포트 범위에서 예를 들어 51422 같은 번호를 즉석에서 빌려준다.
서버는 항상 443번에서 기다리고 있지만, 클라이언트 쪽 포트는 접속할 때마다 달라진다.
소켓은 "IP 주소 + 포트 번호"의 조합이다. 예를 들어 203.0.113.5:443은
이 지구상에 하나뿐인 통신 접점을 가리킨다. 그런데 실제 TCP 연결 하나를 완전히 식별하려면
소켓 하나가 아니라 4개의 값(4-tuple)이 모두 필요하다.
4-tuple = (내 IP, 내 포트, 상대 IP, 상대 포트)
이 네 가지 조합이 딱 하나라도 다르면 완전히 다른 연결로 취급된다. 그래서 서버의 443번 포트 하나에 수천 명이 동시에 접속해도, 서버는 각 연결을 정확히 구별해서 응답을 섞이지 않게 보낼 수 있다 — 클라이언트마다 IP가 다르거나, 같은 IP라도 포트가 다르기 때문이다.
서버는 203.0.113.5:80 한 곳에서만 기다리고 있다. "클라이언트 연결" 버튼을
누를 때마다 새 클라이언트가 임의의 IP와 임의의 임시 포트로 접속을 시도한다. 목적지(서버 쪽)는
전부 80번으로 똑같은데, 서버가 대체 어떻게 이들을 구별하는지 표를 통해 확인해보자.
| # | 서버 쪽 (고정) | 클라이언트 쪽 (매번 다름) | ||
|---|---|---|---|---|
| 목적지 IP | 목적지 포트 | 출발지 IP | 출발지 포트 | |
파이썬 socket 모듈로 서버가 특정 포트를 bind하고 연결을 listen하는
가장 기본적인 형태다. accept()가 호출될 때마다 새 클라이언트용 소켓이
하나씩 만들어지는데, 이 소켓들이 바로 각기 다른 4-tuple로 구별된다.
# 서버: 0.0.0.0(모든 인터페이스)의 8080번 포트에서 대기 import socket srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) srv.bind(("0.0.0.0", 8080)) # 이 컴퓨터의 8080번 포트를 "내 것"으로 등록 srv.listen() # 이제부터 8080번으로 오는 연결 요청을 받기 시작 # 클라이언트가 접속할 때마다 새 소켓(conn)과 (IP, 포트)가 반환됨 conn, addr = srv.accept() # addr = ('203.0.113.9', 51422) 같은 클라이언트 4-tuple 일부