💡 Application Layer에서 Transport Layer에 바라는 서비스 Application Layer에 서비스 제공 (in TCP/IP 4 계층)
1. data integrity (data 유실 없이 전달) → TCP 제공 2. throughput ex) 최소 x bps이상 보장 → 제공 x 3. timing ex) 내가 보낸 메세지는 x ms 안에 도착하면 좋겠다 → 제공 x 4. security (보안) → 제공 x
TCP, UDP
Transport Layer에서 통신이 이루어지기 위해 크게 TCP, UDP 프로토콜을 사용
TCP (Transmission Control Protocol)
UDP (User Datagram Protocol)
연결형 프로토콜
*연결 설정 : 3-way handshaking *연결 해제 : 4-way handshaking
비 연결형 프로토콜
신뢰성 있는 데이터 전송 (유실/변형 → 재전송 지원)
비신뢰성 데이터 전송 (재전송 미지원)
in-ordered (패킷을 보낸 순서대로 받음)
un-ordered (패킷의 순서를 보장하지 않음)
일대일(unicast) 통신
일대일, 일대다(broadcas), 다대다(multicast) 통신
연속성보다 신뢰성 있는 전송이 중요할 때에 사용
신뢰성보다는 연속성이 중요한 실시간 스트리밍과 같은 서비스에 자주 사용
flow control / congestion control
Error Detection (에러 탐지)
Multiplexing / DeMulitplexing
3-way handshaking, 4-way handshaking
3-way:들려?(SYN) → 응 들려!(ACK) 너도 들려?(SYN) → 응 들려!(ACK) (+HTTP request도 보통 함께 전송)
congestion control : 네트워크 상태를 고려하여 sender의 보내는 속도 조절
TCP segment format
UDP의 경우, TCP에 비해 하는 일이 적기 때문에, 헤더가 비교적 간결함을 확인할 수 있다.
UDP는 Error checking, Multiplexing/DeMulitplexing 정도만 수행한다.
따라서 최대한 노력은 하지만(?) 데이터가 유실될 수도 있고, 순서가 뒤죽박죽 바뀔 수도 있다.
* checksum : segment가 network를 거쳐 오는 동안 msg 부분에 변형이 생겼는지 확인
UDP datagram format
Multiplexing / Demultiplexing
TCP, UDP 모두 제공
컴퓨터에는 여러개의 어플리케이션이 돌아가고, 각 어플리케이션들은 하나 이상의 socket 생성 가능
1) Multiplexing
: 소켓에 의해 Application layer에서 Transport layer로 pkt이 전달될 때,
여러 소켓의 pkt을 수집하여 하나의 segment에 캡슐화하여 Network layer로 전달하는 과정
2)Demultiplexing
: Transport layer 에서 Application layer로 segment가 전달 될 때, 올바른 소켓으로 전달 하는 과정
= 들어온 segment가 어떤 소켓으로 보내져야 할지
→정확한 어플리케이션의 소켓으로 전달해주기 위해 포트넘버를 활용 (in segement의 헤더)
demultiplexing은 들어온 패킷이 UDP인지 TCP인지에 따라 다음 2가지로 나뉜다!
💡 Connectionless demultiplexing (UDP) : dest port # 만 가지고 어떤 socket으로 올려보낼지 판단 (어떤 source IP주소, source port를 갖고 있든 목적지 IP와 포트만 같다면 같은 소켓으로 보냄)
💡 Connection-oriented demultiplexing (TCP) : 4가지 tuple을 가지고 어떤 socket으로 올려보낼지 판단 = ( source IP 주소 / source port # / dest IP 주소 / dest port # ) → connection을 맺은 socket 끼리만 메세지를 주고 받음 !!!
Socket
앞서 계속 언급하던 socket에 대해 정확히 알아보자 !
💡 socket : 서로 다른 machine에 존재하는 process 사이의 메세지 교환을 위해 사용하는 system call library
- message를 상대방 socket에 전달하기 위해서, 각 socket들은 unique한 ID, socket 주소를 가지고 있어야 함 - IP 주소 + port number → 소켓의 unique한 ID로 이용 - ( DNS → IP 주소 / port number → 용도별로 고정되어 있음)
소켓 통신 흐름 (TCP)
TCP System Calls구현을 위해 멀티 프로세스, 멀티 스레드 프로그래밍 사용
💡 소켓 통신 흐름 (TCP)
Server 1 ) socket() - 소켓 생성 (연결 요청 확인하는 일만 수행) 2) bind() - 소켓에 주소(IP+port#) 할당 3) listen() - 연결 요청 대기 4) accept() - 연결 요청 수락 (새로운 소켓을 생성해서 클라이언트와 연결 = 실제 통신) 5) read() / write() - 데이터 송수신 (버퍼 이용) 6) close() - 클라이언트와 연결에 사용했던 소켓, accept() 로 만들었던 소켓 종료 (2개) ** 듣기 소켓과 연결소켓의 구분을 통해, 통신 중에도 다른 클라이언트의 연결 요청을 받아들일 수 있음
Client 1 ) socket() - 소켓 생성 2) connect() - 소켓 연결 (3 way handshaking) 3) read() / write() - 데이터 송수신 (버퍼 이용) 4) close() - 소켓 연결 종료 (4-way handshaking)
소켓 통신 흐름 (UCP)
UDP System calls
💡 소켓 통신 흐름 (UDP)
Server 1 ) socket() - 소켓 생성 2) bind() - 소켓에 주소(IP+port#) 할당 3) recvfrom() / sendto() - 데이터 송수신 (datagram)
Client 1 ) socket() - 소켓 생성 2)recvfrom() / sendto() - 데이터 송수신 (datagram) 3) close() - 소켓 연결 종료
** UDP 소켓은 연결 설정이 필요하지 않으므로 listen(), accept() 함수를 호출하지 않음
RDT ( Reliable data transfer protocol)
신뢰성 있는 데이터 교환
송/수신하는 데이터가 오류 없이 온전히 전송되는 것
Transport Layer(전송계층)에서는 신뢰성 있는 데이터 교환을 하고 싶어 하지만, 하위 레이어에서의 신뢰성을 보장할 수 없기 때문에 문제가 발생할 수 있음 → 이를 해결하기 위해 Transport Layer에서 RDT 프로토콜을 이용할 수 있음
그렇다면 신뢰성 있는 교환은 뭘까? 신뢰성이 있다는 말은 다음과 같은 의미를 갖는다.
💡 신뢰성이 있다 = 비트 에러 (bit error)가 없음 = 패킷 손실 (packet loss)이 없음
FSM(finite state machines)을 이용해
rdt가 어떻게 동작하는지 간단하게 디자인 해보기 위해
sender와receiver를 나눈 후, stop and wait 방식의단방향 통신이라 가정
( 즉, Data는 Sender → Reciver )
* stop and wait : sender sends one packet, then waits for receiver response(ACK/NAK)
rdt 1.0 (reliable transfer over a reliable channel)
network가 reliable channel이라고 가정 (즉 비트 에러, 패킷 손실이 없는 경우)
rdt는 딱히 할 일이 없음 (데이터를 패킷으로 만들어서 전송 / 패킷에서 데이터 추출)
rdt 2.0 (channel with bit errors)
network에서 비트 에러는 발생하지만, 패킷 손실은 일어나지 않는다고 가정
error checking mechanism 필요
ACKs(Acknowledgements) : 수신 측이 송신 측에게 패킷을 제대로 받았다고 알림
NAKs(Negative Acknowledgements) : 수신 측이 송신 측에게 패킷에 오류가 있다고 알림
error가 없는 경우 / error가 있는 경우
💡 rdt 2.0의 치명적 결함 - ACK/NAK 신호에 오류가 발생하거나 손실될 수 있음 (수신 측 무한정 대기) - ACK/NAK 신호에 중복이 발생해 패킷이 중복으로 재전송될 수 있음
rdt 2.1
패킷에 seq #(순서 번호)을 추가해서 rdt 2.0의 문제점을 해결
sequence number를 통해 receiver는 새로운 msg인지, 버려야하는 재전송된 msg인지 판단
stop and wait 가정 → 순서 번호는 0과 1이면 충분 (중복인지, 아닌지 판단)
sender / receiver
rdt 2.2 (NAK-free protocol)
rdt 2.1과 같은 기능을 가짐
NAK 대신 ACK 만을 사용
중복되는 ACK 신호를 받으면 현재 패킷을 다시 재전송
ex) 1번 pkt 오류 탐지 → ACK 0 전송 → 1번 pkt 재전송
rdt 3.0 (channels with errors and loss)
network에 비트에러, 패킷 손실이 모두 발생 가능한 경우 (현실적)
타이머 이용 (ACK를 "합리적인" 시간 동안 기다리고, ACK가 도착하지 않으면 패킷을 재전송)
정상적으로 전달된 경우 (A) / 패킷이 중간에 손실된 경우 (B) / ACK가 손실된 경우 (C) / ACK 신호 전달이 지연된 경우 (D)
💡 rdt 3.0의 문제점 - ACK신호가 지연되면, 계속해서 중복으로 패킷과 ACK 신호가 재전송되는 문제가 발생 - 데이터를 하나 보내고 ACK 신호를 기다릴 때까지 다음 데이터를 보내지 않아 성능이 좋지 않음