segment를 받는 상대의 상태에 맞게, 적절하게 데이터를 조절해서 보내는 것이다.
이를 어떻게 판단할 수 있을까? 그렇다. 상대의 Recv buffer의 상태를 보면 된다.
Recv buffer 상태를 보고, '나 공간이 5만큼만 남았으니까 고려해서 보내'
라고 전달을 하면 될 것아닌가? 이걸 어디에 실어서 보낸다고?
그렇지, Segment Header에 Recv buffer가 존재한다.
이를 보면서 전달 양을 서로 조절할 수 있는 것이다.
여기서 잠깐, '전달하는 양 조절'과, '전송 속도'는 서로 다른 의미인가 생각해보자.
똑같은 말이다.
만약, Recv buffer에 남은 공간이 없으면 어떻게 될지 가정해보자.
segment를 보낼 때 공간이 0이라고 보낼 것이다.
그러면 Sender는 어떻게 해야되는가? 진짜 보내지 말아야 하는가?
아니지, 다르게 접근해보자.
지금 왜 Recv buffer에 공간이 없을까?
이걸 App 레이어로 보내야 되는게 그게 안되니까 그런거 아닌가?
내가 메시지를 보내고, 그 뒤에 App 레이어에 뭉탱이로 보내서 공간이 날 수도 잇다.
그래서 Sender는 DATA만 비워서 보낸다.
그럼 답이 올테고, 그 안에 Recv buffer가 공간이 나는지 계속 확인이 가능한 것이다.
몽말인지 이해가지?
클라이언트가 메시지를 먼저 보내야 겠지.
1. Header에 SYN을 위한 1비트가 있다. 여기에 1을 채우고, 랜덤 Seq#를 담아 보낸다.
2. 서버는 본인이 메시지를 보낼 때 사용할 랜덤 Seq#을 설정하고, 마찬가지로 SYN 비트 1, ACKbit 1
응답으로 ACK Num = x + 1, ACK bit = 1로 응답한다.
3. 클라이언트가 ACK num = y + 1, ACK bit = 1에 다가 "메시지"를 담아서 보낸다.
(ex. HTTP면 HTTP req를 보낸다.)
여기서 잠깐,
ACK num은 다음에 기대하는 바이트의 시퀀스 번호를 말한다.
근데 ACKbit은 뭔가?
TCP 헤더의 플래그 필드에서 확인 응답을 나타내는 비트다.
1일 경우 ACK num 필드를 유효한 값으로 사용하고 있다는 것이다.
'나는 이전 데이터 잘 받았고, 지금 ACK num 잘 참고해라'
라는 뜻이다.
요약하자면, ACK을 보낼 때, ACKbit이 무조건 1이고, '나 ACK num 보냈음'을 알리는 표시다.
또 하나 이상한 점이 있다.
3 way handshake니까, 세번 왔다 갔다 하는 걸 알 수 있는데,
저 다음은 어떻게 되는거지? 서버가 다시 보내야 할 거 같은데?
저 마지막 3번째 과정은, 우리가 알고 있는 클라이언트가 서버에 요청 보내는 것이 맞다.
저 과정 내부에 메시지를 함께 담아서 보내는 것이다. 마치 HTTP req 처럼 말이다.
왜 굳이 저 마지막 3번이 필요하냐고?
서버 입장에서 봐라. '연결해도 돼~' 라고 보냈는데, 답이 안오면, 얘를 기다려야돼 말아야돼.
할 거 아닌가.
클라 입장에서도 봐라. handshake를 왜 하냐? 메시지 보내려고 하는 거 아닌가?
그니까 보내는 것이다.
클라이언트가 먼저 끊자고 말한다. => FIN
서버가 알았다고 하고, 데이터 보낼거 다 보내고 FIN한다. 그리고 close. => ACK, FIN, close
클라는 알았다고 하고 기다린 후 연결 끊는다. => ACK, close.
여기서 왜 클라이언트가 타임 아웃으로 기다리는 걸까?
FIN을 서버로부터 받기 이전에, 오기로 한 데이터가 안왔다면? 기다려야지.
그리고 ACK을 보냈으니까, 이걸 서버가 받았는지 모르니까 기다리는것이다.
지금까지는 상대방과 나의 상태만 고려해서 메시지를 주고 받았다.
그런데 사실, 하나가 더 있다. 내 메시지를 운반해주는 도로, Network 말이다.
이건 내가 통제할 수 있는 영역이 아니다. Public한 영역이기 때문에.
TCP를 생각하면서 보자.
네트워크가 느리다. 중간에 유실된다. 그럼 내가 하는 것은? 재전송이다.
똑같은 데이터를 몇 번이고 보낸다. 나만 그럴까? 모두가 그런다.
즉 데이터를 무식하게 쏟아 부을수록 나만 손해라는 것이다.
내 손해가 모두의 손해다.
그럼, 네트워크가 혼잡한지 어떻게 알 것인가? 누가 알려줌?