TCP 프로토콜
- 연결을 지향하므로 UDP보다 데이터를 안정적으로 순서대로, 에러없이 교환할 수 있다.
- UDP보다는 안전하지만 느리다.
TCP 프로토콜의 구조
- Offset: 여기서는 헤더의 길이를 의미한다.
- Reserved: 예약된 필드로, 사용하지 않는다.
- TCP Flags: TCP가 통신하면서 상대방과의 연결 상태를 확인하는데, 어떤 플래그를 사용하는 지에 따라서 '데이터를 보내도 되는지 확인 하는' 것인지, '연결 초기화'를 하려는지, '데이터를 보내는지', '급한 데이터인지' 등등을 표기한다.
👉 플래그는 꼭 하나만 세팅 되지는 않으며 동시에 여러개가 세팅 되기도 함
- U: Urgent
👉 긴급 비트로, 현재 보내는 데이터가 우선순위가 높은 데이터가 포함되어 있음을 의미한다.
👉 U가 1로 세팅되면 급한 데이터임을 의미한다.
👉 뒤에 나오는 Urgent pointer와 관련이 있다.
- A: Acknowledgment
👉 승인 비트로, 데이터를 보내도 되는지 물어본 것에 대한 '승인'을 할 때 사용함
- P: Push
👉 밀어넣기 비트로, 원래 데이터를 추가적으로 전송하려면 TCP 버퍼(데이터를 받을 수 있는 공간)가 일정 크기만큼 쌓여야 하는데 이것 상관 없이 데이터를 밀어넣겠다는 뜻(잘 사용하지 않는다.)
- R: Reset
👉 초기화 비트로, 연결된 상태에서 추가적으로 데이터 주고 받으려 하는데 문제가 발생해서 새로고침 할 때 사용
- S: Sync(가장 중요함! ⭐⭐⭐)
👉 동기화 비트로, 상대방과 연결 시작할 때 무조건 사용하며 이것이 보내지고 난 다음에 둘 사이의 연결이 동기화 되기 시작함
👉 sync 비트를 받은 이후에는 서로 상태를 주고 받으며 상태를 계속 동기화 시킴
- F: Fin
👉 종료 비트로, 연결을 끊을 때 사용한다.
- Urgent Pointer: 어디서부터가 긴급 데이터인지 알려주는 위치값(Flag가 U일 때 사용)
- Window: 상대방과 연결된 상태에서 데이터를 줄 때 데이터를 보내도 되는지, 데이터를 잘 받았는 지를 확인하기 위해 사용한다.
👉 현재 나한테 남은 공간이 얼마인지 상대방에게 알려준다.
- TCP Options: IP protocol에서의 option과 같은 역할로 붙는다면 4byte씩 가능하고 10개까지 가능하다.
👉 따라서, TCP 프로토콜은 기본 20바이트인데 최대 60바이트까지 늘어날 수 있다.
TCP를 이용한 통신과정
연결 수립 과정
"연결 수립 과정"이 가장 중요하다. 대부분의 네트워크 통신은 TCP를 이용한다.
👉 이 과정이 끝나야 데이터가 전달 된다.
- 클라이언트가 서버에게 요청 패킷을 보낸다.
- Ethernet + ipv4 + TCP(포트번호 80) 패킷을 보낸다.
👉 Flag: SYN, Sequence Number: 100, Acknowledgement:0
(Seq, Ack 번호는 임의다.)
-
서버가 클라이언트의 요청을 받아들이는 패킷을 보낸다.
👉 Flag: SYN + ACK, Sequence Number: 2000, Acknowledgement: 101
(동기화가 된 이후이기 때문에 Ack 번호는 클라이언트 요청에서의 Seq 번호 + 1이 된다. Seq 번호는 처음 보내는 것이기 때문에 임의의 번호가 된다.)
-
클라이언트는 이를 최종적으로 수락하는 패킷을 보낸다.
👉 Flag: ACK, Seq: 101, Ack: 2001
(마찬가지로 Ack 번호는 받은 Seq 번호 + 1이 되고, Seq 번호의 경우 처음 보내는 것이 아니라 답장을 보내는 것이기 때문에 seq 번호는 받은 Ack 값을 이용한다.
⚡ 이 3개의 과정을 '3way handshake'라 부른다.
⚡ 연결 수립 과정이 끝난 후에 클라이언트가 서버에 요청을 보내게 될 것이다.
(참고적으로 Seq num + Ack 값을 계산해서 클라이언트인 척 하고 서버에 요청을 보내는 경우가 생길 수 있다. 이를 session-hijacking이라 한다. 네이버에 로그인된 내 연결을 뺏어가면 내가 로그인한 페이지를 그대로 받아와서 나쁜 짓을 할 수 있다!)
데이터 송수신 과정
⚡ 연결 수립 과정에서 이어서 이제는 클라이언트가 서버에 다시 패킷을 보낸다.
- 보낸 쪽에서 또 보낼 때는 SEQ 번호가 ACK 번호가 그대로다.
- 받는 쪽에서의 SEQ 번호는 받은 ACK 번호가 된다.
- 데이터를 주고받을 때는 페이로드가 있기 때문에 받는 쪽에서의 ACK 번호는 받은 "SEQ 번호 + 데이터의 크기"가 된다.
가령, 네이버에 웹툰을 요청할 경우 아래의 과정을 거치게 된다.
- 클라이언트 -> 웹 서버
- 데이터 크기: 100
- Flag: PSH + ACK
👉 클라이언트가 웹 서버로 요청을 다시 보낼 때, 이전에 사용했던 SEQ, ACK 번호를 그대로 사용해서 보낸다.(위에서 101, 2001이므로 이렇게 보낸다.)
- S: 101, A: 2001
- 웹 서버 -> 클라이언트
- 데이터 크기: 500
- Flag: PSH + ACK
- S: 2001, ACK: 201(클라이언트가 보낸 데이터의 크기가 + 100 되었다.)
- 클라이언트 -> 웹 서버
- S: 201, ACK: 2501(웹 서버가 보낸 데이터 크기가 +500 되었다.)
TCP 상태전이도
중요한 상태 변화 두 가지가 있다.
- LISTEN: 서버에서 포트번호를 사용하고 있는 상태(클라이언트의 요청을 듣고 있는 상태)
👉 요청하면 서버가 응답을 해줄 수 있는 상태
- ESTABLISHED: 연결이 서로 수립된 상태
👉 3way handshake 과정이 끝나서 통신이 가능한 상태
데이터 송수신 과정에 TCP 상태를 추가해서 생각할 수 있다.
- 클라이언트 -> 웹 서버: 패킷 보냄
- 클라이언트: SYN_SENT 상태
- 웹 서버: LISTENING 상태
- 웹 서버 -> 클라이언트: 패킷 받음
- 클라이언트: -
- 웹 서버: SYN_RECEIVED
- 클라이언트 -> 웹 서버: 패킷 보냄
- 클라이언트: ESTABLISHED
- 웹 서버: ESTABLISHED
⚡ Listening 상태에서 Established 상태가 되어야 데이터를 주고받을 수 있게 된다.