TCP와 UDP
서론
저번 게시물에서는 TCP/IP 프토로콜의 4가지 레이어가 어떤 일을 하며, 어떻게 동작하는지에 대해 알아봤었습니다.
그 중에서 Transport Layer는 데이터의 순차적이고 안정적인 전달을 담당하며, 출발지의 포트번호와 도착지의 포트번호를 헤더에 담아 도착지 컴퓨터에 데이터가 도착하면, 도착 포트를 읽어와 해당 포트에 있는 프로세스로 데이터를 전달합니다.
이러한 Transport Layer에서 사용하는 프로토콜은 대표적으로 두가지가 있는데요, 바로 TCP와 UDP입니다.
그럼 이 둘은 어떤 차이가 있는지 알아보도록 하겠습니다.
TCP
TCP 프로토콜은 Transmission Control Protocol의 약자로써, 신뢰성있고 순차적인 데이터를 보장합니다. 쉽게 풀어서 표현하면, TCP 프로토콜을 사용하면 데이터가 유실되지 않고, 섞일 일도 없이 안전하게 전달 될 수 있다는 것이죠.
그럼 어떠한 방식을 사용하길래 데이터를 안전하게 전달 할 수 있도록 도와준다는 것일까요?
먼저, Transport Layer가 TCP 프로토콜을 사용하게 되면 세그먼트에 TCP 헤더가 추가되는데, 이 헤더에 대해서 알아 봅시다.
TCP 헤더
위 사진이 바로 TCP 헤더의 모습인데요. 뭔가 여러가지의 정보가 있는 것을 확인 할 수 있습니다.
이중에서 먼저 Source port 와 Destination port가 눈에 띕니다.
Source Port, Destination Port
앞서 Transport Layer에서는 목적지 포트에 데이터를 전달한다고 했었습니다. 이 부분이 바로 출발지 포트와 목적지 포트의 번호가 저장되어있는 부분입니다. 데이터가 도착하면 이 포트 번호에 할당된 프로세스로 이 데이터를 전송합니다.
Sequence Number
다음은 Sequence Number입니다. 이 숫자는 데이터의 순서를 보장하기 위한 부분으로, 데이터가 클 경우에는 데이터를 쪼개서 보내기 때문에 이 데이터가 섞이지 않도록 순서를 Sequence Number에 적어서 보내게 됩니다.
Sequence Nubmer는 최초 데이터 전송시에 랜덤한 수로 초기화 되며, 이후 자신이 보내게 될 데이터 1bytes당 시퀀스 번호가 1씩 증가하면서 보내집니다.
예를들어 5바이트의 데이터를 전송한다고 가정해봅시다.
그렇다면 랜덤으로 먼저 첫번째 데이터의 Sequence Number를 초기화 하겠죠? 랜덤으로 0으로 초기화 됐다면, 첫번째 데이터는 0, 두번째는 1, 세번째는 2… 이와같이 랜덤으로 초기화 된 번호에서 1바이트당 1씩 증가합니다.
Acknowledgement Number
Acknowledgemnt Number는 수신자가 다음으로 받기로 예상되는 번호를 의미합니다.
예를 들어보겠습니다. 마찬가지로 5바이트의 데이터를 보낸다고 가정하면, Sequence Numbers는 앞서 설명한대로 0,1,2,3,4의 순차적인 숫자를 갖게 될 것입니다. 그럼 송신 쪽에서는 Acknowlegement Number에 5를 보냄으로써 다음으로 받아야 할 Sequence Number의 번호를 보냄으로써 다음으로 보내야할 데이터의 시작점을 알려줍니다.
따라서 Acknowledgement Number는 상대방이 처음 보낸 시퀀스 번호 + 자신이 받은 데이터의 Bytes가 된다는 것을 알 수 있습니다.
Data Offset
이 부분은 세그먼트중에서 헤더가 아닌 데이터가 시작되는 부분을 표현해주는 부분입니다.
예를들어 (실제로는 이렇지 않지만 이해를 쉽게 하기 위해 간략화 해서 표현하겠습니다.) 00001111 의 데이터가 있고, 0000이 헤더고 1111이 데이터라면, Data Offset에 5가 적혀있다면 이 세그먼트의 데이터는 5번째 데이터 부터구나~ 라고 컴퓨터가 알 수 있게 되는 것이죠.
Reserved
Reserved는 미래를 위해 예약된 필드로, 모두 0으로 채워져야합니다.
Flags
이 비트들은 현재 세그먼트의 속성을 나타내는 부분입니다. 여러가지 비트 플래그가 채워지고 비워진 상태를 확인 함으로써 이 데이터가 현재 어떤 요청을 보내고 있는지 확인 할 수 있습니다.
필드 | 의미 |
---|---|
URG | Urgent Pointer(긴급 포인터) 필드에 값이 채워져있음을 알리는 플래그. 이 포인터가 가리키는 긴급한 데이터는 높게 처리되어 먼저 처리된다. 요즘에는 많이 사용되지 않는다. |
ACK | Acknowledgment(승인 번호) 필드에 값이 채워져있음을 알리는 플래그. 이 플래그가 0이라면 승인 번호 필드 자체가 무시된다. |
PSH | Push 플래그. 수신 측에게 이 데이터를 최대한 빠르게 응용프로그램에게 전달해달라는 플래그이다. 이 플래그가 0이라면 수신 측은 자신의 버퍼가 다 채워질 때까지 기다린다. 즉, 이 플래그가 1이라면 이 세그먼트 이후에 더 이상 연결된 세그먼트가 없음을 의미하기도 한다. |
RST | Reset 플래그. 이미 연결이 확립되어 ESTABLISHED 상태인 상대방에게 연결을 강제로 리셋해달라는 요청의 의미이다. |
SYN | Synchronize 플래그. 상대방과 연결을 생성할 때, 시퀀스 번호의 동기화를 맞추기 위한 세그먼트임을 의미한다. |
FIN | Finish 플래그. 상대방과 연결을 종료하고 싶다는 요청인 세그먼트임을 의미한다. |
위 6개의 플래그는 기존에 사용하던 6개의 비트 플래그이며, 후에 혼잡제어 기능의 향상을 위해서 3개의 플래그 비트가 더 추가되었습니다.
이를 ECN(Explicit Congestion Notification)이라 하며, 네트워크의 혼잡 상태를 알리기 위한 방식입니다.
기존에는 타임아웃을 이용한 방식을 통해서 일정 시간이상 응답이 없으면 이를 네트워크 혼잡 상태로 판별하여 처리했지만, 처리속도가 아주 민감한 어플리케이션에서는 이러한 대기시간을 줄이는 것이 더 좋기 때문에, 이러한 3개의 플래그비트를 추가하여 네트워크의 혼잡도를 명시적으로 표시하여 알립니다.
필드 | 의미 |
---|---|
NS | ECN에서 사용하는 CWR, ECE 필드가 실수나 악의적으로 은폐되는 경우를 방어하기 위해 RFC 3540에서 추가된 필드 |
ECE | ECN Echo 플래그. 해당 필드가 1이면서, SYN 플래그가 1일 때는 ECN을 사용한다고 상대방에게 알리는 의미. SYN 플래그가 0이라면 네트워크가 혼잡하니 세그먼트 윈도우의 크기를 줄여달라는 요청의 의미이다. |
CWR | 이미 ECE 플래그를 받아서, 전송하는 세그먼트 윈도우의 크기를 줄였다는 의미이다. |
ECN은 따로 다룰 정도로 많은 내용이 있기 때문에, 알아두기만 하고 자세한 설명은 따로 다루도록 하겠습니다.
Window Size
Window Size 필드에는 한번에 전송할 수 있는 데이터의 양을 의미하는 값을 담습니다.
예를 들어, 한번에 10비트의 파일을 10개로 나누어 sequence number를 0,1,2…10까지 보낸다면 이 데이터들은 각각 10이라는 window size를 갖게 되는 것이죠.
Checksum
Checksum은 데이터를 송신하는 중에 발생할 수 있는 오류를 검출하기 위한 값입니다.
TCP의 Checksum은 전송한 데이터를 16Bits씩 나누어 모두 더한 후, 이를 1의 보수를 취해주어 나온값을 사용하여 전송된 데이터에 오류가 있는지를 확인합니다.
예를 들어, 11011011 이라는 데이터가 있다면 (실제로는 16비트씩 나누어 계산하지만, 예시에서는 4비트로 간단하게 생각해보겠습니다.)
4비트씩 나누어 (실제로는 16비트) 모두 더해줍니다.
1101 + 1011 = 11000
근데 이렇게 하면 4비트(실제로는 16비트)를 넘어서서 Checksum의 길이를 초과하게 됩니다. 이럴때는 앞에있는 캐리(두개의 수를 더했을때 자리수가 올라간 부분)을 떼어내어 다시 이 값에 더해줍니다.
1000 + 0001 = 1001
이러한 방법을 Wrap Around라고 합니다.
이제 이 값의 1의 보수를 취해주면 됩니다. 1의보수는 쉽게 말하면 2진수값을 모두 반전 시킨 값으로, 1001 의 경우는 0110이 됩니다.
따라서 이 데이터의 Checksum은 0110이 됩니다. 이 Checksum과 데이터의 총합인 1001을 더하면 어떻게 될까요?
당연히 1의 보수를 취한값이니 모두가 1로이루어진 수가 나올 것입니다. 따라서 송신측에서는 위 과정을 통해 Checksum을 만들어 송신하고, 수신측에서는 받은 데이터를 위 과정을 거쳐 값을 만든 뒤 Checksum과 더해봄으로써 정상적인 1로만 이루어진 값이 나오는지 확인합니다.
이런 방식을 쓰면 데이터가 중간에 손상되었는지 알 수 있을 것입니다. 전달받은 데이터를 더한 뒤, 이를 Checksum과 더해서 0이 있는지를 확인하면 됩니다.
Urgent Pointer
말그대로 urgent한 pointer, 긴급한 포인터입니다. 먼저 처리가 필요한 데이터를 표시합니다. 만약 5바이트의 데이터가 있고 Urgent Pointer가 1이라면, 두번째 데이터를 먼저 처리할 것입니다.
정리
TCP는 위와 같은 기능등을 통해서 안전한 연결을 보장합니다.
Sequence Number를 통해서 들어온 데이터의 순서도 보장하며, 플래그 비트를 통해서 통신을 하기전에 올바르게 통신이 가능한 상태인지 확인하는 3-Way-HandShake를 통해 데이터가 올바르게 수신되었는지도 확인합니다. 게다가 마지막에 Checksum을 통해서 데이터가 혹여나 손상되었는지 확인하니, 안전하게 데이터를 송수신 할 수 있겠죠?
그럼 UDP는 어떨까요?
UDP
UDP는 User Datagram Protocol로, 이도 마찬가지로 Transport Layer에서 사용하는 프로토콜입니다.
UDP는 위에서 말한 TCP와 같은 역할을 하지만, TCP가 제공하는 기능들 중에 단 두가지만 지원합니다.
바로 포트번호와 Checksum입니다. 따라서 출발지와 도착지 포트를 갖고 해당 포트에 도착한 뒤, Checksum을 사용해서 데이터가 손상되었는지만을 확인합니다.
그럼 기능이 TCP가 압도적으로 많은데, UDP는 왜 필요할까요?
TCP와 UDP의 차이
TCP와 UDP의 가장 큰 차이점은 무엇일까요? 바로 TCP는 연결 지향 프로토콜 임에 반해, UDP는 비연결 지향 프로토콜이라는 것입니다.
이것이 무슨 뜻일까요?
TCP의 경우는 데이터를 송신하기전에, SYN과 ACK 플래그 비트를 통해서 현재 통신이 가능한 상태인지 확인하는 3-Way-Handshake과정을 거친다고 했습니다.
위처럼 통신전에 클라이언트는 SYN 비트가 1인 데이터를 보내고, Server가 이를 받으면 ACK과 SYN이 1인 데이터를 또 보낸뒤, 이것이 만약 클라이언트측이 정상적으로 수신했다면 마지막으로 ACK을 보내면서 현재 통신이 원활한 상태, 연결되었다는 것을 확인하는 것이죠.
심지어 데이터의 Sequence Number를 통해서 순서까지 보장해주니, 통신의 신뢰성이 보장됩니다.
하지만 TCP의 단점은 무엇일까요?
아무래도 데이터 통신을 보낼때마다 3번의 확인을 통해 연결을 확인하니, 속도가 떨어질 것입니다.
반면 UDP의 경우는 여러 확인과정이 없으니 속도는 TCP에 비해서 매우 빠르겠죠?? 하지만 역시 확인과정을 거치지 않는 UDP는 통신의 신뢰성이 보장되지 않습니다. 연결이 안된상태라도 이를 데이터 송신자가 알수도없고, 순서가 잘못되도 이것이 잘못된 것인지 알 수 없죠. 평균적으로 7퍼센트의 데이터가 유실된다고 합니다.
따라서 데이터의 신뢰성보다는 속도가 중요하다면 UDP를, 데이터의 신뢰성이 중요하다면 TCP를 사용하게 되는 것입니다.
마무리…
이처럼 TCP와 UDP는 어떤 차이점을 갖고있고, 어떤 상황에 따라 어떤 프로토콜을 써야하는지 알아봤습니다.
공부해보니 왜 TCP가 주류 프로토콜로 사용되는지 잘 알 수 있었습니다. 다음 게시물에서는 TCP에 대해서 자세히 알아보도록 하겠습니다.
댓글남기기