JJ BLOG

Ruby on Rails로 웹개발을 하고있는 웹개발자입니다.

TCP/IP

31 Dec 2018 » DataScience

TCP/IP


1. TCP/IP

컴퓨터와 네트워크 기기가 상호간에 통신하기 위해서는 서로 같은 방법으로 통신을 해야합니다. 때문에 서로간에 그 규칙이 필요합니다. 이를 프로토콜이라고합니다. TCP/IP를 찾아보면 계층에 대한 설명이 항상 따라옵니다. 앞선 포스팅에서 OSI 7계층에 대해서 설명했는데요. OSI 7계층은 네트워크 전송 시 데이터 표준을 정리한 것입니다. 이 이론을 실제 사용하는 인터넷 표준이 TCP/IP 4계층입니다.

tcp_ip

이렇게 계층화를 하면 하나의 사양을 변경할 시, 해당 계층만 변경해도 문제를 해결할 수 있습니다. 각 계층은 연결되어 있는 부분만 결정되어 있기 때문에 각 계층의 내부는 자유롭게 설계할 수 있습니다.

제일 위에서부터 사용자가 HTTP를 통해 서버에 Request를 보내려합니다. 이때 한가지 소개할 부분이 또 생깁니다.


2. 소켓(Socket)

프로토콜에는 내부 메모리가 있습니다. 이 메모리에 통신 동작을 제어하기 위한 제어정보를 기록합니다. 이 메모리의 영역을 소켓이라고 할 수 있습니다. 대표적인 제어 정보로 상대의 IP 주소, 포트번호, 통신 동작의 진행상태 등이 포함됩니다. 데이터의 송수신은 ‘데이터 통로’를 통해 수행됩니다. 이 ‘데이터 통로’의 역할을 소켓이 하는 것입니다. 이 소켓(데이터 통로)를 연결하는 출입구의 역할을 ‘포트’가 합니다.

소켓이 생성되면서 디스크립터라는 것이 생성됩니다. 디스크립터는 소켓을 식별하는 역할을 합니다. 소켓을 식별하는 이유는 동시에 여러 개의 소켓이 생길 수 있기 때문입니다. 소켓이 하나라면 우리는 사이트 하나를 방문할 때 동시에 다른 사이트를 방문하지 못하게 됩니다. 이렇게 여러 웹 서버와의 소켓을 식별하도록 디스크립터가 생성되는 것입니다.

자 이제 소켓이 생성되고 디스크립터가 소켓을 식별했습니다. 상대 웹 서버에게 데이터가 도달했습니다. 여기까지의 과정을 ‘접속’이라고 합니다. 소켓의 역할은 여기서 끝이 아닙니다. 서버 측에 요청을 보냈고 응답이 오게되면 소켓은 수신 동작을 합니다. 응답해온 데이터를 애플리케이션 내부의 버퍼에 저장하고 데이터 송수신이 끝나면 연결을 끊습니다.

소켓이 접속 동작을 마치면 데이터를 전달해야합니다. HTTP 리퀘스트 메시지로 패킷을 전달합니다. 패킷은 데이터를 일정한 크기로 자른 단위로 인터넷에서 정보를 전달하는 단위입니다. 나누어진 패킷이 순서대로 도착한다는 보장이 없기 때문에 규칙이 필요합니다. TCP는 이 패킷을 재조립하고 패킷에 손상이 있거나 손실된 패킷이 있다면 재전송을 요청합니다.

앞서 말씀드렸듯 TCP에는 패킷이 올바르게 도착하지 않았으면 재전송을 요청합니다. 요청을 받은 TCP는 다시 전송을 합니다. 따라서 TCP는 패킷을 송신한 후에 확인 동작을 합니다. TCP가 데이터를 패킷으로 나눌 때 해당 조각이 몇번째 바이트에 해당하는지를 세어둡니다. 이후 세어둔 값을 TCP 헤더에 기록합니다. 이를 시퀀스 번호라고 합니다. 이 시퀀스 번호는 ACK 번호가 됩니다. 송신측에서 ACK 번호를 TCP 헤더에 기록하여 보내면 수신측에서는 이 수신된 ACK 번호를 기록하여 송신측에게 알려줍니다. 이러한 방식을 이용하면 누락된 데이터가 있는지 확인할 수 있습니다. 이러한 동작을 수신 확인 응답이라고 합니다.

수신측에서 데이터를 받아 문제가 없으면 ACK 번호를 송신측에 다시 보내주고 데이터 조각을 수신 버퍼에 일시적으로 보관합니다. 이후 패킷을 연결하여 데이터를 원래 모습으로 복원한 뒤 애플리케이션에게 건네줍니다.

이제 클라이언트와 서버 간의 데이터 송수신 과정이 끝났습니다. 이 과정이 끝나면 연결 끊기 단계에 들어갑니다. 서버 측에서 TCP헤더를 만들고 여기에 연결 끊기를 나타내는 FIN 비트에 1을 설정합니다. 이후 IP에 의뢰하여 클라이언트에 송신합니다.

클라이언트는 FIN이 1로 변경된 TCP 헤더를 받고 자신의 소켓에 상대방이 연결을 끊는 동작에 들어갔다고 알립니다. 패킷을 받았다는 ACK를 반송하고 애플리케이션에 데이터를 건네줍니다. 서버에서 보낸 데이터를 전부 수신했다는 사실을 브라우저에게 알리고 서버와 똑같이 FIN을 1로 설정 후 TCP 헤더를 만들어 보내고 서버에서 ACK 번호가 돌아오면 서버와의 연결이 끝이 납니다.