본문 바로가기

Dev.Basic/네트워크

[2장] 1. TCP/IP - 소켓을 작성하고 서버에 접속한다.

이 포스팅은 '성공과 실패를 결정하는 1%의 네트워크 원리' 책을 기반으로 작성되었습니다.

2장. TCP/IP Outline

1. 소켓을 작성하고 서버에 접속한다.
2. 데이터를 송수신 한다.
3. 서버에서 연결을 끊어 소켓을 말소한다.
4. IP와 이더넷의 패킷 송수신 동작
5. UDP 프로토콜을 이용한 송수신 동작


2장 첫번째. 소켓을 작성하고 서버에 접속한다.

1. 프로토콜 스택의 내부구성
프로토콜 스택 내부는 데이터 송수신을 담당하는 TCP, UDP와 패킷 송 수신 동작을 제어하는 IP로 나누어져 있다. 브라우저나 메일 등의 일반적인 애플리케이션이 데이터를 송수신 할 경우 TCP 프로토콜을 사용하며 DNS 서버에 대한 조회 등 짧은 제어용 데이터를 송수신 할 경우에는 UDP 프로토콜을 사용한다. IP내부에는 ICMP와 ARP를 포함하고 있다. ICMP는 패킷을 운반할 때 발생하는 오류를 통지하거나 제어용 메시지를 통지할 때 사용하고, ARP는 IP 주소에 대응하는 이더넷의 MAC 주소를 조사할 때 사용한다.

IP 아래에는 LAN 드라이버가 있다. LAN드라이버는 LAN 어댑터의 하드웨어를 제어하고(?) LAN 어댑터가 실제 송수신 동작 즉 케이블에 신호를 송수신하는 동작을 수행한다.



2. 소켓의 실체는 통신 제어용 제어정보
프로토콜 스택은 내부에 메모리 영역을 갖고 있어서 그곳에 통신 동작을 제어하기 위한 제어정보를 기록한다. 이 제어정보를 또는 제어정보가 기록되어 있는 메모리 영역을 소켓이라고 할 수 있다. 대표적인 제어정보로는 통신 상대의 IP 주소, 포트번호, 통신 동작의 진행상태 등을 포함한다.
프로토콜 스택은 소켓 즉, 이 제어 정보를 참조하면서 동작한다. 소켓을 만든다는 동작은 제어 정보를 추가하고 상태를 기록하거나 송수신 데이터를 일시적으로 저장하는 버퍼 메모리를 준비하는 등 통신을 준비하는 작업입니다.



3. 프로토콜 스택의 동작 원리
애플리케이션에서 socket을 호출하여 프로토콜 스택에 소켓 만들 것을 의뢰한다. 이에 응답하는 프로토콜 스택은 한 개의 소켓을 만든다.
최초로 하는 일은 소켓 한 개 분량의 메모리 영역을 확보하는 것이다. 그리고 그 메모리 영역에 제어정보를 기록하면서 초기 상태임을 알리는 정보까지 기록한다. 다 만들어지면 소켓을 나타내는 디스크립터를 애플리케이션에게 알려준다. 디스크립터를 받은 애플리케이션은 이 디스크립터를 통해서 소켓과 소통한다.



4. 접속이란?
소켓 생성을 의뢰해서 애플리케이션의 프로토콜 스택에 소켓이 만들어졌다. 소켓을 만든 직후에는 초기상태이므로 아무 것도 기록되어 있지 않다. 따라서 통신 상대가 누군지도 모른다. 브라우저만이 알고 있는 IP 주소나 포트 번호를 프로토콜 스택에 전달해줘야 하는 것이다. 이렇게 전달해주는 동작이 접속의 일부이다.

서버 측은 어떤가?
클라이언트 측과 마찬가지로 서버 측에서도 소켓이 만들어졌지만, 만드는 동작만으로는 통신 상대를 알 수 없다. 그래서 클라이언트가 서버에게 통신하려는 클라이언트가 존재한다는 것을 전달한다. 그러면 서버 측 프로토콜 스택도 클라이언트의 정보를 가질 수 있게 된다. 이것도 접속의 일부이다.

접속 동작의 첫번째 동작은 통신 상대와의 사이에 제어정보를 주고받아 소켓에 필요한 정보를 기록해서 소켓이 데이터 송수신이 가능한 상태로 만드는 것이다. 접속 동작에서 주고 받는 제어정보는 통신 규칙으로 정해져 있으므로 규칙에 따라 접속동작을 실행하면 필요한 정보가 전달되고 데이터를 송수신할 수 있는 상태가 된다.

데이터 송수신 동작을 실행할 때 데이터를 일시적으로 저장하는 메모리 영역이 필요하다. 이 메모리 영역을 버퍼메모리라고 한다. 이 메모리를 확보하는 과정을 포함하여 접속한다는 동작을 정의한다.



5. 맨 앞부분에 제어정보를 기록한 헤더를 배치한다.
제어정보에는 크게 두 가지가 존재한다. 하나는 클라이언트와 서버가 서로 연락을 절충하기 위해 주고 받는 제어정보이고, 다른 하나는 소켓에 기록하여 프로토콜 스택의 동작을 제어하기 위한 정보이다.

전자에 대한 내용을 TCP 프로토콜 사양으로 규정하고 있다. 접속 동작 뿐만 아니라 데이터를 송수신하는 동작이나 연결을 끊는 동작도 포함하여 통신 동작 전체에서 어떤 정보가 필요한지 검토하는 것이다. 규정된 제어 정보가 헤더 (여기에서는 TCP 헤더가 되겠다.)에 담기게 된다. 즉 클라이언트와 서버 사이에 주고 받는 패킷의 맨 앞부분에 위치하게 된다. 이렇게 클라이언트와 서버는 이 헤더에 필요한 정보를 기록하여 연락을 취하면서 통신 동작을 진행하고 있다.

또다른 제어 정보로 소켓에 기록되는 제어 정보가 있다. 여기에는 애플리케이션에서 통지된 정보, 통신 상대로부터 받은 정보 등이 수시로 기록된다. 프로토콜 스택은 이 소켓의 제어정보를 차례로 참조하면서 움직인다. 



6. 접속 동작의 실제
애플리케이션이 Socket 라이브러리의 connect를 호출하면서 시작된다.
connect(<디스크립터>, <서버측 IP주소, 포트 번호>)
명령이 프로토콜 스택의  TCP 담당 부분으로 전달된다. 프로토콜 스택의 TCP 담당 부분은 서버의 TCP 담당 부분과 제어 정보를 주고 받는다.

이 주고 받는 과정에도 절차가 있다.
우선 제어 정보를 기록한 헤더를 만든다. 클라이언트 측 TCP에서 헤더를 만들면 이것을 IP 담당 부분에게 건네주어 송신을 의뢰한다. IP 담당 부분에선 서버 측 IP 담당 부분에게 전달하고 서버측 IP 담당 부분은 받은 헤더를 TCP 부분에게 건네준다. 서버 측 TCP 담당 부분은 건네 받은 TCP 헤더를 조사하고, 해당하는 소켓에 정보를 기록한다. 그리고 접속 동작이 '진행 중'이라는 상태가 된다. 이 과정을 마치면 서버의 TCP 담당 부분은 응답을 돌려보낸다. 클리이언트와 마찬가지로 헤더를 만들고, IP 담당 부분에 반송을 의뢰하여 진행한다. 이 과정은 패킷을 받았다는 것을 알리기 위한 동작이다.

클라이언트 측에서 아직 수행할 작업이 남아있다. 서버 측으로부터 응답을 받으면 소켓에 접속 완료를 나타내는 제어 정보를 기록해둬야 한다. 그리고 패킷이 제대로 도착했다는 것을 서버에 알리기 위해 (ACK 비트를 1로 만들어)TCP 헤더를 반송한다.

이것이 서버에 도착하면 접속 동작의 대화가 끝이 난다.

이렇게 생겨난 파이프 같은 것을 커넥션이라고 한다. 또한 커넥션은 데이터 송수신을 계속하는 동안 close를 호출하여 연결을 끊을 때 까지 계속 존재한다. 이렇게 해서 커넥션이 이루어지면 프로토콜 스택의 접속 동작이 끝나므로 connect의 실행이 끝나면서 애플리케이션을 제어할 수 있게 된다. 



2장 첫번째 end