TCP(Transmission Control Protocol/Internet Protoco) 프로토콜은 신뢰할 수 없는 공용망에서도 정보유실 없는 통신을 보장하기 위해 세션을 안전하게 연결하고 데이터를 분할하고 분할된 패킷이 잘 전송되었는지 확인하는 기능이 있습니다.
패킷에 번호(Sequence Number)를 부여하고 잘 전송되었는지에 대해 응답(Acknowledge Number)합니다.
또한, 한꺼번에 얼마나 보내야 수신자가 잘 받아 처리할 수 있는지 전송 크기(Window Size)까지 고려해 통신합니다.
TCP의 여러 역할 덕분에 네트워크 상태를 심각하게 고려하지 않고 특별한 개발 없이도 쉽고 안전하게 네트워크를 사용할 수 있습니다.
TCP에서는 분할된 패킷을 잘 분한하고 수신측이 잘 조합하도록 패킷에 순서를 주고 응답번호를 부여합니다. 패킷에 순서를 부여하는 것을 시퀀스 번호, 응답 번호를 부여하는 것을 ACK 번호라 부릅니다. 두 번호가 상호작용해 순서가 바뀌거나 중간에 패킷이 손실된 것을 파악 할 수있습니다.
TCP에서는 유실없는 안전한 통신을 위해 통신 시작 전 사전 연결작업을 진행합니다. 목적지가 데이터를 받을 준비가 안 된 상황에서 데이터를 일방적으로 전송하면 목적지에서는 데이터를 정상적으로 처리할 수 없어 데이터가 버려집니다.
TCP 프로토콜은 이런 상황을 만들지 않기 위해 통신 전, 데이터를 안저하게 보내고 받을 수 있는지 미리 확인하는 작업을 거칩니다. 패킷 네트워크에서는 동시에 많은 상대방과 통신하므로 정확한 통신을 위해서는 통신 전, 각 통신에 필요한 리소스를 미리 확보하는 작업이 중요합니다. TCP에서는 3번의 패킷을 주고 받으면서 통신을 서로 준비하므로 '3방향 핸드셰이크'라고 부릅니다.
TCP는 이런 3방향 핸드쉐이크 진행 상황에 따라 상태(State) 정보를 부르는 이름이 다릅니다.
서버에서는 서비스를 제공하기 위해 클라이언트의 접속을 받아 들일 수 있는 LISTEN 상태로 대기합니다.
클라이언트에서 통신을 시도할 떄 Syn 패킷을 보내는데 클라이언트에서는 이 상태를 SYN-SENT라고 부릅니다.
클라이언트의 Syn을 받은 서버는 SYN-RECEIVE 상태로 변경되고 Syn, Ack로 응답합니다.
이 응답을 받은 클라이언트는 ESTABLISHED 상태로 변경하고 그에 대한 응답을 서버로 다시 보냅니다.
서버에서도 클라이언트의 이 응답을 받고 ESTABLISHED 상태로 변경됩니다.
ESTABLISHED 상태는 서버와 클라이언트 간의 연결이 성공적으로 완료되었음을 나타냅니다.
Wireshark로 해당 장비가 TCP의 통신과정을 패킷단위로 캡쳐해 보았습니다.
캡처할 필터는 다음과 같습니다.
필터 : ip.addr==192.168.203.205(캡처대상장비 IP) && tcp.port==80
cmd창 열어서
프롬프트에서
curl www.google.com
한 이후에 캡쳐된 패킷입니다.
seq와 ack의 숫자는 관계가 있는데, 한 쪽에서 seq로 보내주면 ack=seq+1로, 받아주는 역할을 한다.
client(54036) -> server(80)
seq=0
client가 서버로 seq=0을 넣어서 서버에 연결 요청을 함.[SYN]
클라이언트는 상태가 된다. SYN-SENT
server(80) -> client(54036)
seq=0, ack=1
server가 client로 부터 seq=0을 받고 ack(0+1)=1로 응답.[ACK]
server가 seq=0로 요청을 보냄.[SYN]
client(54836) -> server(80)
seq=1, ack=1
client가 server로 부터 seq=0을 받고, ack(0+1)=1로 응답.[ACK]
client가 server로 seq(0+1)=1 ,
연결 전의 seq=0 이 아닌
시퀀스가 아닌 다음 시퀀스를 보내달라고 요청을 함.
ESTABLISHED 상태의 Client가 Server로 FIN 을 보내 연결을 종료 신호를 보낸다.
보낸 이후 연결종료를 기다리는 FIN-WAIT-1 상태로 변해 Server로 부터 수신을 기다린다.
ESTABLISHED 에서 FIN을 받고, ACK를 Client로 날린다.
종료 신호인 FIN을 받은 Server는 Close를 기다리는 CLOSE-WAIT 상태로 바뀌고, ACK를 Client로 보낸다.
LAST-ACK 상태로 변경한다.
ACK를 기다리는 클라이언트는 ACK를 받고 FINE-WAIT-2 상태가 된다.
서버도 종료를 알리기 위해서 FIN 신호를 클라이언트로 보낸다. 그리고
LAST-ACK상태로 변한다.
FIN 명령을 받고, TIME-WAIT 상태로 변경된후, Server로 ACK를 날린다.
그 후 CLOSED 상태가 된다.
ACK를 받은 서버는 CLOSED 상태가 된다.
책: 엔지니어를 위한 네트워크 입문
http://www.tcpipguide.com/free/t_TCPConnectionTermination-2.htm
http://www.tcpipguide.com/free/t_TCPConnectionEstablishmentProcessTheThreeWayHandsh-3.htm