컴퓨터공학

TCP에 대하여

아, 그래요? 2022. 1. 6. 13:35
TCP (Transmission Control Protocol) 이란?
The Transmission Control Protocol (TCP) is one of the main protocols of the Internet protocol suite. TCP provides reliable, ordered, and error-checked delivery of a stream of octets (bytes) between applications running on hosts communicating via an IP network. 
TCP is connection-oriented, and a connection between client and server is established before data can be sent. The server must be listening (passive open) for connection requests from clients before a connection is established. Three-way handshake (active open), retransmission, and error-detection adds to reliability but lengthens latency. 

 

위 글은 TCP에 대한 위키피디아의 설명을 요약한 글이다. 정리해보자면 다음과 같다.

 

  • TCP는 인터넷 프로토콜의 대표적인 프로토콜 중 하나이다.
  • TCP는 신뢰성(reliable), 순서보장(ordered), 에러검증(error-checked) 기능을 제공한다.
  • TCP는 연결 지향의 통신 방식으로 데이터를 주고 받기 전에 서버와 클라이언트 간의 연결(conection)이 필수적이다.
  • TCP는 3-way handshacke, 재전송(retransmission) 및 에러 검출(error-detaction)을 수행함으로써 높은 신뢰성을 보장하지만, 그만큼 높은 레이턴시를 발생시킨다.

 

연결 지향 (connect oriented) 네트워킹이란?

TCP는 연결 지향 통신 방식이다. 그러면 연결을 지향하지 않는 통신방식도 있느냐? 그렇다. 추후에 다룰 UDP (User Datagram Protocol)가 대표적인 비연결 지향 통신 방식이다. 이때 연결 지향과 비연결 지향의 차이점은 실제 데이터를 전송하기전 각 시스템 간의 연결이 되어 있어야 되는지 여부에 따라 갈린다. TCP와 같은 연결지향 방식은 호스트와 클라이언트 간에 어떤 방식이든 연결이 되어있어야 통신이 가능하고, 연결이 끊어지면 통신이 불가능하다.

// Server
Socket socket = ServerSocket.accept();

// Client
Socket socket = new Socket();
socket.connect(new InetAddress("localhost", 3001));

다음은 자바에서 제공하는 Socket 객체를 활용한 TCP 통신 코드이다. 위 코드를 보면 서버와 클라이언트가 각자의 메소드를 이용하여 연결을 요청하고 있다.(connect() : 연결요청 / accept() : 연결수락) 위와 같이 TCP 통신은 먼저 서버와 클라이언트가 연결을 해야 이후 데이터 발신및 수신이 가능하다.

 

이때 서버는 반드시 클라이언트로 부터 연결 요청을 듣기위한 작업을 해야하는데 이를 Passive Open이라고 한다. 이후 클라이언트가 연결을 요청하면 3-way handshake 과정을 통해 연결이 성립되고 이 과정을 Active Open이라고 한다.

 

3-way Handshake (Connection Establishment)

3-way Handshake는 서버가 Passive Open을 했을때, 클라이언트가 해당 서버에 연결을 요청하면서 시작된다. 이 과정은 3개의 step으로 이루어져 있다.

 

  1. 클라이언트가 서버에게 SYN 플래그를 전송한다. 클라이언트는 세그먼트의 시퀀스를 임의의 숫자(X)로 설정한다.
  2. 서버는 그에 대한 응답으로 클라이언트에게 SYN-ACK 플래그를 전송한다. 서버는 Acknowlegment Number는 세그먼트 시퀀스보다 1 증가한 숫자(X+1)로 설정한다. 그리고, 세그먼트의 시퀀스를 임의의 숫자(Y)로 다시 설정한다.
  3. 클라이언트는 다시 ACK 플래그를 전송한다. 이때 시퀀스를 Acknowlegement Number의 값으로 설정(X+1)하고, Acknowlegment Number는 기존 시퀀스의 1 더한 숫자(Y+1)로 설정한다.

이 과정을 마치면 연결이 설립(Establishment)되고, 양방향 통신(Full-duplex communication)이 가능하게 된다.

 

 4-way Handshake (Connection Termination)

4-way Handshake (출처: wikipedia)

4-way Handshake는 클라이언트가 서버에게 연결을 종료할 것을 요청하면서 시작된다. 총 4개의 스탭으로 이루어져 있다.

 

  1. 클라이언트가 서버에게 FIN 플래그를 전송한다. (FIN_WAIT)
  2. 서버는 응답으로 ACK 플래그를 전송한고 자신의 통신이 끝날때까지 기다린다. (CLOSE_WAIT)
  3. 서버가 연결을 종료할 준비가 되면 클라이언트에게 FIN 플래그를 전송한다. (LAST_ACK)
  4. 클라이언트는 다시 서버에게 ACK 플래그를 전송하며 연결을 종료한다. (TIME_WAIT -> CLOSED)

이때 서버에서 클라이언트로 FIN 플래그를 전송하면 클라이언트는 TIME_WAIT 상태가 된다. 이때 클라이언트는 일정 시간 동안 종료하지 않고 대기한다. 그 이유는 서버가 FIN 플래그를 전송하기 전에 전송한 패킷이나 데이터가 FIN플래그보다 늦게 도착할 수 있기 때문이다. 이 경우 클라이언트가 플래그를 받자마자 종료해 버리면 해당 패킷이나 데이터는 전부 유실되게 된다. 이를 방지하기 위해 FIN 플래그를 받은 클라이언트는 일정시간 대기하고 종료된다.

 

# half-duplex close sequence

리눅스나 HP-UX와 같은 운영체제의 경우, 호스트가 연결을 완전히 끊었음에도 불구하고, 아직 읽지 못한 데이터가 존재할 경우, 호스트는 클라이언트에게 FIN 플래그 대신, RST 플래그를 전송한다. 그렇게 되면 해당 클라이언트는 데이터가 유실되었음을 알 수 있다. 이 과정은 Half-Duplex Close Sequence라고 한다.

 

Half-open state (반 연결 상태)

반 연결 상태란 말 그대로 한쪽은 연결이 종료되었는데, 나머지 한쪽은 아직 연결된 상태이다. 이 경우에도 제한적이지만 통신이 가능하다. 연결된 쪽에서는 여전히 데이터 전송이 가능하고, 연결이 종료한 쪽에서도 이 데이터를 읽을 수 있다. 하지만 연결이 종료된 쪽에서의 데이터 전송은 당연히 불가능하다.

 

TCP의 사용

TCP는 다양한 어플리케이션및 시스템에서 사용된다. 대표적으로 World Wide Web, P2P 파일 쉐어링, SSL/TLS 등이 TCP를 사용한다. 하지만 TCP는 높은 수준의 신뢰성 보장과 유용한 에러 검출및 처리 기능을 제공하지만 그에 따른 레이턴시를 요구한다. 그렇기 때문에 제한 시간내에 작업을 처리해야 하는 실시간 컴퓨팅 등에서는 그다지 합리적인 방식이 아니다. 이러한 경우네는 RTP(Real-time Transport Protocol)이나 UDP를 사용하는 것이 적절하다.

 

여담

본 글은 위키피디아의 'Transmission Control Protocol' 문서를 기반으로 작성하였다. 컴퓨터네트워크에 대한 지식이 전무하다보니 위키피디아 글을 읽고 이해하는데 한계가 많았고, 위글도 내가 이해한 내용에서 최대한 정확하게 쓰려고 노력했다. 자바에서 TCP 통신을 구현하다 우연히 궁금해서 알아 봤는데 컴퓨터 네트워크 공부가 절실한 것 같다...