Nagle 알고리즘은 TCP 통신의 혼잡 제어를 위한 알고리즘으로, 작은 패킷이 네트워크를 통해서 과도하게 전송되는 것을 방지하여, 통신의 효율성을 높이는 알고리즘이다. "Tinygram Problem"을 해결하기 위한 알고리즘이다.
Tinygram Problem이란, 작은 패킷이 네트워크를 통해 과도하게 전송 될때 발생하는 문제점을 말하는 것이다.
TCP/IP 네트워크의 통신에서 패킷은 전송하는 데이터 뿐만 아니라, 패킷의 헤더를 포함하여 전송하게 되는데, 이때, 작은 사이즈의 데이터를 전송하기 위해서 용량이 비교적 큰 헤더와 함께 보내는 것이 비효율적이라는 것이다.
1바이트의 데이터를 보내는데, 패킷의 헤더 사이즈가 20바이트라면, 1바이트의 데이터를 전송하기 위해 총 21바이트 (1 바이트의 데이터 + 20 바이트의 헤드)의 데이터를 전송 해야한다. 이러한 작은 크기의 데이터를 지속적으로 전송한다면, 네트워크 대역폭이 낭비되고, 네트워크가 혼잡해진다.
위와같은 문제를 해결하기 위해 등장한 알고리즘이 Nagle 알고리즘이다.
Nagle 알고리즘은 데이터를 전송 후 전송된 패킷의 응답이 오기 전까지 다음으로 전송 할 데이터를 버퍼에 모아놓았다가, 전송한 패킷에 대한 ACK 응답을 받으면, 모아놓은 데이터를 한번에 전송하는 방법이다.
즉, 쉽게 말하면, 최초로 트럭으로 택배를 보낸 후 상대방이 택배를 받고, 받았다는 응답을 확인 하기 전까지, 트럭에 택배를 계속 쌓아 두다가, 응답이 오면 모아둔 택배를 한번에 전송하는 방식이다.
이러한 방식으로 데이터를 전송하면, 작은 데이터를 지속적으로 전송 할 필요 없이 응답이 오기 전까지 데이터를 모아두고 전송하기 때문에, 데이터를 효율적으로 전송 할 수 있다.
하지만, 이러한 방법은 ACK 응답이 오기 전까지는 대기하기 때문에 전송 지연이 발생 할 수 있고, 만약 지연 ACK 알고리즘과 함께 동작 할 경우, 지연 데드락이 발생 할 수 있다.
패킷에 대한 응답 ACK를 전송 하는것도 네트워크 자원을 소모한다. 이러한 자원 소모를 방지하고 네트워크 효율을 위해서 전송 받은 패킷에 대한 응답 ACK를 지연시키고, 상대 호스트에 전송할 패킷을 기다리며 전송할 패킷과 응답 ACK를 함께 전송 하는 방식이다.
지연 데드락은 Nagle 알고리즘과 지연 ACK가 함께 동작했을때 발생한다. 실제로 데드락 처럼 동작이 정지 되는 상황은 아니고, 서로의 응답을 기다리면서 지연 시간이 늘어 나는것을 의미한다.
지연 데드락은 다음과 같이 발생한다.
1. 호스트 A가 데이터를 B에게 전송하고, B의 ACK 응답을 기다린다.
2. A에게 데이터를 받은 B가 ACK 응답을 하기 전 다른 데이터와 함께 ACK를 전송하기 위해 대기한다.
3. B에게로 부터 ACK 응답을 받지 못해서 대기한다.
위의 상황과 같이 서로의 응답을 대기하며, 대기 시간이 길어진다.
Nagle 알고리즘을 사용하면, 네트워크 지연이 발생 하는데, 빠른 데이터 전송이 필요한 상황이라면, 비활성화 하는것이 좋다.
TCP 소켓을 생성 할 때 기본적으로 Nagle 알고리즘은 활성화 되어 있다. Nagle 알고리즘을 비활성화 하기 위해서는 소켓의 TCP_NODELAY의 옵션을 이용해 비활성화 할 수 있다.
int option = TRUE;
int optlen = sizeof(option);
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void*)&option, optlen);
TCP_NODELAY 값을 1로 설정하면, Nagle 알고리즘이 비활성화 된것이고, 0으로 설정하면 활성화 된다.