계층 3의 프로토콜은 ICMP, IGMP, IP 등이 있지만, ICMP와 IGMP 프로토콜은 모두 IP를 도와주는 프로토콜이므로 계층 3을 대표하는 프로토콜은 IP이다. 계층 4에서의 대표적인 프로토콜 2개에는 TCP와 UDP가 있다. 이제 TCP, UDP에 대해서 알아보자.
계층 4의 프로토콜이 다뤄야 할 문제
- 송신자가 데이터를 보내는 속도가 수신자에 비해 너무 빠를 경우, 수신자는 받은 데이터를 감당할 수 없기 때문에, 속도를 일치시켜줘야 한다.
- 데이터그램의 중복을 제거하고 손실 되었을 경우 감지 및 복구시켜줘야한다.
- 패킷이 너무 늦게 오는 문제.
- 정체현상(Congestion) 처리 문제.
- 송수신자가 서로 합의하에 통신해야 하는 경우가 있을 수 있다.
- 위와 같은 문제들은 IP가 다 해결할 수 없으니, 계층 4의 프로토콜이 해결해야 한다.
End-to-End principle
실제 통신은 호스트와 또 다른 호스트가 통신하는 것이 아닌, 호스트 내의 “프로그램”을 통해 통신한다. 프로그램과 프로그램이 통신 이처럼 호스트 내 프로그램 간의 통신을 End-to-End 라고 한다. TCP, UDP 모두 End-to-End 통신이다.
- IP는 Best-effort한 통신이다, 이 말인 즉슨, 통신에 대한 결과를 보장하지 않는다(신뢰성이 없다). 보내긴 보냈지만 결과는 모른다.
- 하지만 End-to-End 에선 신뢰성을 보장해줘야한다.
- 정보를 전달하는 중간 과정은 단순히 전달하는 역할의 치중하고, 보다 복잡한 처리(에러처리 등)는 양 끝단(end)에서 처리하자는 것이다.
- TCP, UDP 모두 End-to-End 통신이다.
End-to-End에서 Endpoint를 표현하는 방법.
- Endpoint는 프로그램이기 때문에, 한 호스트 내에서 데이터를 주고 받을 프로그램의 주소를 표현하는 방법이 있어야 한다. -> 이를 port number를 사용해서 표현한다.
- OS의 pid(현재 프로세스의 id)를 사용하면 될 것 같지만 그렇게 하지 않고 port number를 쓰는데에는 두가지 이유가 있다.
- 이 세상의 모든 OS가 같은 pid를 제공하지 않는다(공통된 방법이 없음)
- 동일한 pid를 제공한다고 하더라도 pid를 쓸 수 없다. 이유는 바로 서버-클라이언트 구조의 특성 때문인데, 서버는 클라이언트의 접속을 감지하기 위해 계층 4에 본인의 주소를 등록해야 한다. 그런데 주소의 등록은 자기 자신의 주소를 알아야 할 수 있는 것이고, 그렇게 하기 위해서는 프로그램이 실행되기 전에 주소를 알아야 한다는 의미이다. 따라서 pid는 프로세스가 실행되었을 때 부여되는 것이므로, port 번호를 따로 사용하게 되는 것이다.
well-known port number: 1~1024 번으로 구성된 이미 등록된 포트 번호이다. TCP, FTP, SSH 등에 쓰인다. 1024~5만 몇번 까지 서버가 쓴다.그 이상은 클라이언트가 쓴다.
계층 4의 기능들.
- 어플리케이션 demultiplexing
- 데이터의 전송을 제어
- Flow-control: 수신자의 속도에 맞춰서 수신자가 받고싶은 만큼 보내는 것. 수신자에 대한 정보가 필요하다.
- Congestion-control: 도중에 있는 path나 router에서 데이터가 너무 많아서 처리를 못하면 사용한다. 일단 정체되어 있는 지를 알아야 하는데, 수신자나 네트워크가 정체됐다고 알려주거나 혹은 송신자가 packet을 보내서 around time을 확인하고 시간이 어느정도 길어지면, 길이 막혔다고 판단하고 보내는 데이터의 양을 줄인다.
- 데이터의 순서를 식별하기 위해 각각의 패킷에 일련번호를 붙여준다.
- 신뢰성을 보장하고 정확한 정보를 제공하기 위해, Acknowledgement를 사용한다. 수신자가 Acknowledgement를 보내면, 송신자는 데이터를 재전송 한다. -> congestion avoidance, slow starter
UDP(User Datagram Protocol)
UDP의 특징
- 비연결 지향적(Connectionless-oriented) 인 통신이다. 패킷을 만들어서 수신자의 동의없이 무조건 보낸다.
- UDP에서의 패킷은 User Datagram 혹은 Segment라 부른다.
UDP의 사용
- bootstrapping 할 때 사용된다.( 컴퓨터가 처음 IP를 발급받을 때의 broadcasting에 사용됨)
- 멀티미디어(VoIP, 오디오, 비디오)를 전송할 때 사용된다.
- 받은 데이터에 소소한 에러가 발생해도 지장이 없다. 정확도보다 실시간이 중요할 때 사용된다. 즉, 절대적인 신뢰성이 필요하지 않을 때 사용된다.
- Message oriented 통신이다. 즉, 응용 프로그램이 준 데이터를 자르지 않고 그대로 전송하는 방식이다.
- 받은 데이터가 에러가 발생 했더라도, 계층 5에서 그 에러를 감지하고 수정할 수 있다면 UDP를 사용한다.(TCP에 비해 더 빠르고 가볍기 때문에)
- OS와 독립적이다.
TCP
- 연결 지향적(connection-oriented) 통신이다. 송신자와 수신자가 결정되어서 1:1로 통신한다.
- TCP에서의 패킷은 Segment라 부른다.
- Stream 패러다임을 사용한다.
- 패킷을 byte들의 연속으로 보고, 보낼 수 있는 만큼만 잘라서 보낸다.
- 신뢰성(보낸 정보가 수신자에게 정확히 도착해야 한다.)을 제공해야한다.
- Connection, 데이터 통신, Disconnection 세 방면에서 모두 신뢰성을 제공해야 한다.
Connection에서 TCP가 신뢰성을 보장하는 방법.
3-way hand shake
[STEP 1] 클라이언트는 서버에 접속을 요청하는 SYN 패킷을 보낸다. 이때 클라이언트는 SYN 을 보내고 SYN/ACK 응답을 기다리는SYN_SENT 상태가 되는 것이다. 서버는 listen 상태가 된다.
[STEP 2] 서버는 SYN요청을 받고 클라이언트에게 요청을 수락한다고 ACK 와 SYN flag를 보내는데 ACK는 SEQ 번호가 N인 것을 반환된 값이고 SYN은 M+1으로 보낸다.
[STEP 3] 클라이언트는 서버에게 ACK을 보내고 이후로부터는 연결이 이루어지고 데이터가 오가게 되는것이다. 이때의 B서버 상태가 ESTABLISHED 이다. 그 ACK 안에있는 SEQ 번호에는 M+1을 담고, ACK 번호에는 N+1을 담아서 보낸다.
4-way hand shake
[STEP 1] 클라이언트가 연결을 종료하겠다는 FIN플래그를 전송한다.
[STEP 2] 그러면 Server가 FIN 받았다고 ack를 보내고 모든 일을 다 끝낼 때까지 기다렸다가 FIN을 보낸다. 서버는 일단 확인메시지를 보내고 자신의 통신이 끝날때까지 기다리는데 이 상태가 TIME_WAIT상태다.
[STEP 3] 클라이언트는 확인했다는 메시지를 보낸다.
그런데 만약 “Server에서 FIN을 전송하기 전에 전송한 패킷이 Routing 지연이나 패킷 유실로 인한 재전송 등으로 인해 FIN패킷보다 늦게 도착하는 상황”이 발생한다면 어떻게 될까요? Client에서 세션을 종료시킨 후 뒤늦게 도착하는 패킷이 있다면 이 패킷은 Drop되고 데이터는 유실될 것입니다.이러한 현상에 대비하여 Client는 Server로부터 FIN을 수신하더라도 일정시간(디폴트 240초) 동안 세션을 남겨놓고 잉여 패킷을 기다리는 과정을 거치게 되는데 이 과정을 “TIME_WAIT” 라고 합니다.
참조 https://t1.daumcdn.net/cfile/tistory/2152353F52F1C02835