Silly Window Syndrome이란 데이터 전송을 위한 패킷의 실제 데이터가 IP 주소 또는 Port 번호와 같은 header의 크기보다 작은 경우, 이를 전송하며 생기는 네트워크 낭비를 의미한다.
(e.g. IP, Port를 담은 header의 크기는 40bytes, 실제 데이터는 1byte의 문자)
이걸 해결하는 방법(Nagle 알고리즘)은 다음과 같다.
- 이전 데이터에 대한 ACK 패킷이 도착했을 경우, 실제 데이터가 작아도 그냥 보낸다.
- 이전에 전송한 패킷에 대한 ACK 패킷이 오기 전까지는 MMS(Maximum segement size)의 크기만큼 쌓이지 않는다면 대기시킨다.(MMS만큼 쌓인다면 전송한다.)
이 알고리즘을 사용하지 않으면 패킷의 크키가 어떻든 그냥 보낸다.
사용한다면 오른쪽같이 동작하지만 중간에 대기하다. sending 버퍼의 데이터의 크기가 MMS보다 커지면 ACK 패킷이 오기전에 전송한다.
(디폴트는 on이다. 상황에 따라 on/off를 결정해야한다.)
receiver에서도 비슷한 상황이 발생할 수 있다. 이는 만약 receiver의 버퍼가 가득찬 상황에 application이 너무 느리기 때문에 버퍼에서 1byte씩 가져가면 어떻게 될까? rwnd는 1이될 것이고 실제 데이터가 1byte인 패킷이 sender로부터 전송될 것이다. 이 또한 비효율적이다.
이를 해결할 방법은 두 가지이다.
- 버퍼의 수용 가능한 크기가 MMS 이상이거나 반 이상이 비어야한다. 그렇지 않으면 ACK 패킷에 항상 rwnd를 0으로 보낸다.
- 버퍼가 꽉차거나 일정 이상 남아있지 않은 경우 sender는 rwnd를 통해 전송할 패킷의 크기를 결정하는데, 버퍼가 어느정도 남을 때까지 ACK 패킷을 보내지 않는다. 그럼 sender는 더 이상 데이터를 전송할 수 없게된다 .
- 연결요청: client SYN
- 연결 요청 대기 큐: server는 SYN에 대한 SYN+ACK를 보내고 대기 큐에 클라이언트를 대기시킨다.(
gpt는 그냥 ACK이라던데..)- New socket: accpet 함수가 queue에 있는 클라이언와 연결을 완료한다.
SYN Flooding이란, 임의로 정한 IP주소로 소켓을 생성하여 서버에게 연결요청을 계속하는 것이다. 그런데 서버는 임의의로 정한 IP주소를 통해 SYN+ACK 패킷을 보내기 때문에, ACK 패킷을 받지 못할 것이고 waiting queue는 꽉차 정상적인 요청이 들어와도 처리할 수 없을 것이다.
라우터와 같은 하드웨어 장치로 동일한 경로에서 오는 SYN 패킷을 막을 수 있겠지만, 수많은 컴퓨터에서 다양한 경로를 사용해 SYN 패킷을 보내게 되면 막기 힘들어진다. 이를 DDoS라고 한다.
ACK 패킷은 sequence number를 사용하지 않고 이에 대한 응답은 없다.
TCP는 receiver가 순서가 맞지 않는 데이터를 잠깐 저장할 수 있지만, 이는 프로세스로 전달이 되지 않는다.
다음은 ACK 패킷을 효율적으로 보내기 위한 방법들이다.
- Rule 1: 데이터를 수신하면 ACK을 전송한다. 그러나 receiver가 sending 버퍼에 보낼 데이터가 있으면 함께 보낸다.
- Rule 2: Rule 1을 확인하고 보낼 데이터가 없다면 조금(e.g. 50ms) 기다린다. 이때도 데이터가 없으면 ACK 패킷을 보낸다.
- Rule 3: Rule 2와 같이 ACK을 보내지 않고 기다리다가 데이터 패킷 하나가 또 온다면 ACK 패킷을 보낸다.(두 개의 패킷당 하나의 ACK)
만약 receiver가 전송한 ACK이 소멸됐을 경우 sender는 이전에 전송한 패킷들이 소멸됐는지 ACK 패킷이 소멸됐는지 모른다.(데이터 패킷이 몇개던, 위험하다.) 이러한 이유로 두 개의 패킷당 ACK 패킷 하나를 전송하는 방법으로 TCP가 설계되었다.