// 노션에서 이전했습니다. 하향식 네트워킹 3장
목표
- 트랜스포트 계층 원리 ⇒ 프로토콜 적용
- 신뢰적으로 통신 (3.4)
- TCP (3.5)
- 혼잡 제어 (전송률 제어) (3.6)
- TCP (3.7)
- 신뢰적으로 통신 (3.4)
연결지향형 트랜스포트: TCP
(인터넷의 트랜스포트 계층, 연결형, 신뢰적인 트랜스포트 프로토콜)
📌 오류 검출, 재전송, 누적 확인응답, 타이머, 순서번호와 확인응답 번호를 위한 헤더 필드
TCP 연결
특징
- 연결지향형 : 두 프로세스 핸드셰이크 → 애플리케이션 프로세스에서 전송 O
- 핸드셰이크 = 데이터 전송 보장을 위한 세그먼트(기본 환경 세팅) (= TCP 상태 변수 초기화)
- 논리적인 연결 = TCP 상태 공유
- ≠ 회선 연결 (물리적인 연결 TDM, FDM)
- TDM : 시간 분할 다중화
- FDM : 주파수 분할 다중화
- 종단 시스템에서만 동작
- 라우터, 링크 계층 스위치는 동작 X (라우터가 TCP 연결이 되었는지 모른다)
- ≠ 회선 연결 (물리적인 연결 TDM, FDM)
- 전이중 서비스(full-duplex service)
- 호스트 A 프로세스 — TCP 연결 — 호스트 B 프로세스
- 애플리케이션 데이터 A ↔ B (동시에)
- Q : 다른 계층과의 차이
- Q: 하위 계층이 전이중이 아니어도 전송 계층은 전이중이 가능한가요?
- A: 가능합니다.
- 전송계층은 버퍼에 쌓아 둘 수 있습니다.
- 물리계층은 시분할을 이용하여 송/수신하기 때문입니다.
- 결론: 각 계층은 독립적이기에 계층마다 상관이 없다. (추상화)
- 출처: https://datatracker.ietf.org/doc/html/draft-ietf-tcpm-rfc793bis-01
- Q: 하위 계층이 전이중이 아니어도 전송 계층은 전이중이 가능한가요?
- 점대점 : 단일 송신자와 단일 수신자
방식
- 연결 설정 : 세 방향 핸드셰이크(three-way handshake)
- 상황1 : 한 호스트에서 동작하는 프로세스 → 다른 호스트의 프로세스 연결 초기화 1. TCP 연결 : 3-way handshake클라이언트 서버
1 clientSocket.connect((serverName, serverPort) (클라이언트 프로세스 → TCP 클라이언트) 2 특별한 TCP 세그먼트 (→ 서버) 3 특별한 세그먼트 (→ 클라이언트) 4 특별한 세그먼트 (→ 서버)
- 데이터 송수신
- 상황2 : TCP 연결 후 클라이언트 프로세스 → 서버 프로세스 (데이터 송신)
클라이언트 (송신) 서버 (수신)
| 1 | 클라이언트 프로세스 (데이터 생성) | |
| 2 | 소켓 (데이터 스트림 → TCP 송신 버퍼) | |
| 3 | TCP 송신 버퍼 (스트림 MSS 단위로 잘라 세그먼트 생성 → 네트워크) | |
| 4 | 네트워크 (세그먼트를 IP 데이터그램 캡슐화 | |
| → 서버 네트워크) | 네트워크 (데이터그램 수신 후 역캡슐화 | |
| → TCP 수신 버퍼) | ||
| 5 | TCP 수신 버퍼 (세그먼트 재조립) | |
| 6 | 서버 프로세스 (버퍼에서 데이터의 스트림을 읽는다) |
- MSS (Maximum Segment Size) : 최대 세그먼트 크기
- 세그먼트 안의 payload(애플리케이션 계층 데이터)의 크기
- 왜 이름을 이렇게 지었을까?
- 애플리케이션 데이터 → TCP 세그먼트로 캡슐화되는 과정 (메모리 관점)
- 애플리케이션 데이터 스트림 → 소켓 → TCP 버퍼에 복사
- TCP 버퍼 안에서 **세그먼트 단위(MSS)**로 잘라짐
- TCP 버퍼에서 다른 곳으로 복사되어 TCP 헤더 붙여짐
- 네트워크 계층으로 캡슐화
The MSS counts only data octets in the segment, it does not count the TCP header or the IP header. - https://www.rfc-editor.org/rfc/rfc6691.html
※ 가장 큰 링크 계층 프레임의 길이 (MTU: Maximum Transmission Unit)
MTU = TCP/IP 헤더 길이(보통 40바이트) + MSS
MSS = MTU - TCP/IP 헤더 길이

연결 해제 : 4 way handshake
TCP 세그먼트 구조
- TCP 세그먼트 = TCP 헤더 필드 + 데이터 필드
- 데이터 필드 = 애플리케이션 데이터의 일정량 ≤ MSS

- 포트 번호: 출발지 포트(Source port) 및 목적지 포트(Dest port) 번호를 포함 → 다중화, 역다중화에 사용
- 시퀀스 번호 (Sequence number): 바이트 스트림 내에서 해당 세그먼트 데이터의 첫 번째 바이트에 해당하는 번호(세그먼트 단위가 아님). → 신뢰적인 데이터 전송
- 확인 응답 번호 (Acknowledgement number): 상대방으로부터 수신을 기대하는 다음 바이트의 시퀀스 번호 (누적 ACK 방식을 사용). → 신뢰적인 데이터 전송
- 수신 윈도우 (Receive window, rwnd): 흐름 제어를 위해 수신자가 받아들일 의향이 있는(남은) 바이트 수를 나타냄.
- 헤더 길이 필드(header length field): 32비트 워드 단위, TCP 헤더의 길이
- 옵션 필드(option field): MSS 협상 or 윈도 확장 요소, 타임스탬프 옵션 등
- 참고 : RFC 854, RFC 1323
- TCP 플래그 (제어 비트):
- RST, SYN, FIN: 연결 관리에 사용 (설정 + 해제)
- CWR, ECE: 혼잡 알림(Congestion notification)에 사용
- ACK: 확인응답 필드 유용
- PSH : 논리적인 버퍼 체류 시간 0 (바로 애플리케이션 계층으로 전달)
- URG : Urg data pointer(긴급 데이터 포인터 필드), 순서를 무시하고 애플리케이션으로 전달
- 긴급 데이터 포인터 필드 (긴급 데이터의 마지막 바이트의 위치, 시작점은 이미 알고 있으므로)
- 순서 번호
- 바이트 스트림의 관점 (≠ 세그먼트 관점)
- 초기 순서 번호 = 랜덤 (이전 연결과의 혼선을 막기 위해) (초기 A→ B의 ACK 번호는 무시한다.)
- 그림 (예시)
- 순서번호 → 0, 1000, ···
- 500,000 바이트의 파일, MSS = 1000 바이트 → 500 세그먼트

- 확인 응답 번호
- 수신한 이전 세그먼트 순서 번호 + 데이터 페이로드 = 다음 주소
- 왜?
- 포인터 방식 → 다음 주소를 가리키면 데이터에 바로 접근 O
- 왜?
- 누적 확인 응답
- 순서가 틀린다면? → TCP 구현 개발자 마음
- 버리기
- 데이터 보유하고 잃어버린 빈공간 채워질 때까지 기다리기 - 현재 채택
- 수신한 이전 세그먼트 순서 번호 + 데이터 페이로드 = 다음 주소
- 예시 : 텔넷의 순서 번호와 응답확인 번호
- 텔넷 : 원격 로그인을 위해 사용되는 애플리케이션 계층 프로토콜
- 암호화 X, 대화형 애플리케이션 추가 (≠ 대량 데이터 전송 애플리케이션)
- 사용자가 문자를 치면 이게 서버에 갔다 와서 모니터에 보인다. (에코백 echo back)
- 텔넷 : 원격 로그인을 위해 사용되는 애플리케이션 계층 프로토콜

- 예시 (계속해서)
- 텔넷 (계속해서)
- Host A : 클라이언트, 초기 순서 번호 42
- Host B : 서버, 초기 순서 번호 79
- 순서
- 세그먼트 송신: 클라이언트 → 서버
- 헤더 필드
- 순서 번호 : 42
- 데이터 필드
- 문자 C의 1바이트의 ASCII 표현
- 헤더 필드
- 세그먼트 송신: 서버 → 클라이언트
- 데이터 필드에 대한 확인 응답 - 확인 응답 번호
- 문자 반향 - 데이터 필드
- 헤더 필드
- 확인 응답 번호 : 43
- 순서 번호 : 79
- 데이터 필드
- C의 ASCII 표현
- ※ 피기백된다(piggybacked) = 확인응답이 데이터와 함께 전송된다.
- 피기백 : 어부바, 등에 없기
- 데이터 필드에 대한 확인 응답 - 확인 응답 번호
- 세그먼트 송신: 클라이언트 → 서버
- 헤더 필드
- 확인 응답 번호 : 80
- 데이터 필드 X
- 헤더 필드
- 세그먼트 송신: 클라이언트 → 서버
- 텔넷 (계속해서)
728x90