TCP는 신뢰성 제공을 위해 오류 제어를 한다. 오류 제어는 오류가 발생한 세그먼트를 발견하는 메커니즘, 오류가 발생한 세그먼트가 발견되면 오류를 정정하기 위한 메커니즘으로 나눌 수 있다. 이러한 오류 발견 및 정정은 검사합(체크섬), 확인응답, 시간초과 등을 통하여 수행된다.
TCP는 모든 세그먼트에 필수사항으로 16비트 검사합 필드를 기록해야 한다. 수신자는 검사합을 이용해 세그먼트가 손상되었는지 판단하고, 세그먼트가 손상되었다면 손상으로 판명된 세그먼트를 버린다.
검사합 계산을 위하여 의사헤더를 만들어서 추가한다. 왜 검사합을 계산할 때 의사헤더를 포함하는 것일까? TCP 헤더만으로는 IP 헤더의 오류를 검출할 수 없기 때문이다. 만약 IP주소가 잘못 되었거나 프로토콜이 잘못된 경우(예를 들어, 패킷이 TCP이 아니라 UDP로 전송되는 경우)에는 의사헤더의 값으로 오류를 검출할 수 있다.
TCP에서는 세그먼트의 수신을 확인하기 위하여 확인응답을 사용한다. 세그먼트의 수신을 누적되게 확인응답할 수 있도록 설계되었기 때문에 누적 확인응답(ACK; Accumulative Acknowledgement)이라 한다.
확인응답을 하는 몇 가지 경우가 있다.
세그먼트 발신자는 전송하는 각 세그먼트마다 재전송 시간초과(RTO; retransmission time-out) 타이머를 구동한다. 타이머가 만료되면 해당 세그먼트는 훼손되거나 손실된 것으로 간주하고 세그먼트를 재전송한다.
확인응답만을 포함하는 세그먼트에는 시간초과 타이머가 설정되지 않으며, 이러한 세그먼트는 재전송되지 않는다.
TCP에서 RTO값은 가변적이며 세그먼트의 왕복시간(RTT; round trip time)을 기반으로 업데이트된다.
세그먼트는 전송 중 버려지거나, 오류 검출 등의 이유로 수신자에 의해서 버려질 수 있다. 이렇게 세그먼트가 손실되면 재전송하여야 한다.
수신자는 입력 버퍼에 손실된 세그먼트의 자리를 비워놓는다. 빈 공간이 다 채워지기 전까지는 버퍼의 내용을 어플리케이션 계층으로 전달하지 않는다.
세 번째 세그먼트에 대해서 확인응답을 전송하지 않기 때문에 송신 측에서 설정된 타이머는 만료가 될 것이다. 타이머가 만료되면 송신 TCP는 세 번째 세그먼트를 재전송할 것이다.
세 번째 세그먼트가 손실된 경우를 가정해보자. 수신측은 4,5,6번째 세그먼트를 각각 수신할 때마다 확인응답을 전송한다. 그러면 송신 측은 동일한 값을 갖는 세 개의 확인응답 즉, 3개의 중복응답을 수신한다. 중복응답을 3개 수신하면 비록 세 번째 세그먼트에 대한 타이머가 만료되지는 않았지만 빠른 재전송을 위한 규칙에 의거하여 송신 측은 모든 확인응답이 기대하는 세그먼트인 세 번째 세그먼트를 즉시 재전송한다.
TCP는 비연결 지향 프로토콜인 IP 위에서 전송되기 때문에 TCP 세그먼트들은 서로 다른 지연을 가진 서로 다른 경로를 거쳐서 목적지에 도달한다. 따라서 TCP 세그먼트도 지연될 수 있다.
수신 측은 지연 세그먼트를 손실이나 훼손 세그먼트와 동일한 방법으로 처리한다. 또한 지연 세그먼트는 중복 세그먼트로서 재전송된 이후에 도착할 수도 있다.
위의 지연 세그먼트의 경우 수신 측에 의해서 손실로 처리되는 경우에 늦게 도착한 세그먼트는 중복 세그먼트가 된다. 중복 세그먼트가 도착한 경우 중복 세그먼트는 수신자가 기대하는 순서 번호 값보다 적은 순서 번호 값을 가지기 때문에 수신자 TCP는 중복 세그먼트를 버린다.
확인응답이 손실되더라도 다음 확인응답에 의해서 자동으로 대치될 수 있다. ACK는 이전 확인응답을 포함하는 의미이기 때문에 이전의 세그먼트들이 모두 정상적으로 전송되었다는 의미가 된다.
수신자가 rwnd값이 0으로 설정된 확인응답을 전송함으로써 송신자로 하여금 일시적으로 윈도우를 폐쇄한 경우 발생할 수 있다.
윈도우를 폐쇄한 이후 수신 측이 이러한 제한을 없애고자 하지만 전송할 데이터가 없는 경우, ACK 세그먼트를 전송한다. 하지만 이 ACK가 손실된 경우에는 서로 기다리는 교착상태가 된다. 이와 같은 교착상태를 막기 위해 영속 타이머(persistence timer)가 설계되었다.