접속이란
소켓을 만들면 애플리케이션은 connect를 호출하는데 이때 프로토콜 스택은 자기쪽 소켓을 서버측 소켓에 접속한다.
이더넷이나 통신 회선 등의 케이블은 항상 접속된 상태이기 때문에 통신 상대와 제어 정보를 주고받아 소켓에 필요한 정보를 기록하고 데이터 송, 수신이 가능한 상태로 만든다.
- 서버의 IP 주소나 포트 번호를 프로토콜 스택에 알리는 동작
- 서버측에 통신 동작의 개시를 전달
- 송, 수신 데이터를 일시적으로 저장하는 버퍼 메모리 영역을 확보(접속)
제어 정보
- 통신 동작에 이용하는 제어 정보는 두가지
- 헤더에 기입되는 정보
- 소켓(프로토콜 스택의 메모리 영역)에 기록되는 정보
헤더
- 클라이언트와 서버가 대화할 때마다 제어 정보를 부가하는데 접속 동작 단계에서는 데이터 송, 수신이 아직 이루어지지 않아 제어 정보로만 이루어져 있다. 이 제어 정보는 맨 앞부분에 배치하는 곳부터 헤더라고 부른다.
접속 동작
- 애플리케이션이 서버측 IP 주소와 포트 번호를 써서 connect를 호출하면 프로토콜 스택의 TCP 담당 부분에 명령이 전달된다.
- TCP 담당 부분이 IP 주소에 해당하는 서버의 TCP 담당과 대화를 주고 받는다.
- 송신처와 수신처의 포트 번호를 통해 서버측 소켓을 지정하고 SYN 비트를 1로 만들어 TCP 헤더를 만들고 IP 담당 부분에 건네주어 패킷 송신 동작을 실행한다.
- 서버측 IP 담당 부분이 이를 받아 서버측 TCP 담당 부분에 건네주고 서버측 TCP 담당은 TCP 헤더를 조사하여 수신처 포트 번호(서버측 포트 번호)를 알아낸다. 이를 통해 접속할 소켓을 발견하면 소켓에 필요한 정보를 기입하고 응답을 되돌려 보낸다.
- 송신처와 수신처의 포트번호와 SYN 비트 등을 설정한 TCP 헤더를 만들고 ACK 컨트롤 비트를 1로 만든다. 이 비트는 패킷을 받은 걸 알리기 위한 동작이다. 그 후 IP 담당 부분에 TCP 헤더를 건네주고 IP 담당 부분은 클라이언트에 반송한다.
- 패킷이 클라이언트에 돌아오고 IP 담당 부분을 경유하여 TCP 담당 부분에 도착한다. SYN이 1이면 접속 성공이기 때문에 소켓에 서버 IP 주소와 포트 번호 등의 제어 정보를 기록한다. 그 후 서버가 했던 것처럼 ACK 비트를 1로 만든 TCP 헤더를 반송하고 이것이 서버에 도착하면 접속 동작의 대화가 종료된다.
- 이후 데이터 송, 수신이 가능한 상태가 된다. 이 연결을 커넥션이라고 하며 커넥션은 close를 호출하여 연결을 끊을 때까지 존재한다.
데이터 송수신
프로토콜 스택에 HTTP 리퀘스트 메세지를 넘긴다.
- 프로토콜 스택은 받은 데이터를 곧바로 송신하지 않고 내부 송신용 버퍼 메모리 영역에 저장한 후 다음 데이터를 건네기까지 기다린다.
- 데이터의 길이가 애플리케이션의 사정에 따라 다르기 때문에 작은 패킷을 많이 보낸다면 네트워크 이용 효율이 저하되기 때문에 버퍼를 사용한다.
- 따라서 적정한 크기가 찼을 때 데이터 송, 수신 동작을 수행한다.
- 적정한 크기를 판단하는 요소는 MTU라는 매개 변수와 타이밍이다.
- MTU는 한 패킷으로 운반할 수 있는 디지털 데이터의 최대 길이로 이더넷에서는 보통 1,500 byte이다. MTU에는 헤더가 포함되어 있어 이를 제외한 데이터의 최대 길이는 MSS이다. 이만큼 채우고 송신 동작을 수행하면 패킷이 잘게 나누어질 걱정을 하지 않아도 된다.
- 애플리케이션의 송신 속도가 느려지는 경우, MSS에 가깝게 데이터를 저장하면 여기서 시간이 걸려 송신 동작이 지연되어 버퍼에 데이터가 모이지 않아도 적당한 곳에서 송신 동작을 실행해야 한다. 이를 위해 프로토콜 스택은 내부에 타이머를 갖고 이를 통해 일정 시간이 경과하면 패킷을 송신한다.
- MTU를 중시하면 패킷 길이가 길어져 네트워크 이용 효율이 높아지지만 버퍼에 머무는 시간이 길어진만큼 송신 동작이 지연된다. 적당한 크기로 적당한 시간을 두고 송신 동작을 실행해야 한다.
- 애플리케이션에서 데이터 송신 동작 옵션을 지정하여 애플리케이션 사정에 맞는 송신 동작을 가져갈 수 있다.
데이터가 클 때는 분할 한다.
- 데이터의 크기가 MSS를 초과한다면 분할하여 송신한다.
ACK 번호를 사용해 패킷이 도착했는지 확인한다.
- TCP 담당 부분은 데이터를 조각으로 분할할 때 조각이 통신 개시부터 몇번 째 byte에 해당하는 지 세어둔다.
- 데이터 조각을 송신할 때 세어둔 값을 TCP 헤더에 기록한다. 시퀀스 항목에 해당한다.
- 시퀀스 번호를 통해 누락된 패킷을 확인할 수 있다. 1460번째 byte까지 수신 완료한 상태에서 시퀀스 번호가 1461인 패킷이 도착하면 누락이 없는 것을 확인할 수 있다. 만약 2921인 패킷이 도착하면 누락된 것을 확인할 수 있다.
- 누락이 없다면 송신측에 몇번째 byte까지 수신했는 지 TCP 헤더의 ACK 번호에 기록하여 알린다.
- 시퀀스 번호는 보안을 위해 난수로 생성하며 데이터 송,수신 시작전 초기값을 상대에게 알린다. SYN 비트를 1로 설정할 때 초기값을 설정한다.
- 서버도 마찬가지로 시퀀스 번호를 통해 클라이언트가 데이터를 제대로 수신했는지 확인해야 한다.
- 이 구조를 통해 오류가 발생하면 검출하여 패킷을 다시 보내어 회복 처리할 수 있다.
- 서버 다운 등의 이슈로 데이터를 전송할 수 없는 경우 몇 번 시도 후 데이터 송신을 강제로 종료하고 애플리케이션에 통지한다.
패킷 평균 왕복 시간으로 ACK 번호의 대기 시간을 조정한다.
- ACK 번호가 돌아오는 것을 기다리는 대기 시간을 타임아웃 값이라고 한다.
- 대기 시간은 상황에 따라 다르기 때문에 동적으로 변경하여 할당한다.
- ACK 번호가 돌아오는 시간을 항상 계측하여 대기 시간에 반영한다.
윈도우 제어 방식으로 효율적으로 ACK 번호를 관리한다.
- 한 개의 패킷을 전송하고 이를 기다리는 시간 낭비를 줄이기 위해 윈도우 제어 방식에 따라 복수의 패킷을 보낸다.
- 수신 측의 능력을 초과하여 보내게 되는 사태가 일어날 수 도 있다.
- 이를 방지하기 위해 수신측의 버퍼 크기를 TCP 헤더의 윈도우 필드에 담아 송신측에 알려 이 버퍼가 넘치지 않을 정도로만 송신측이 패킷을 전송하도록 한다.
ACK 번호와 윈도우를 합승한다.
- ACK 번호와 윈도우를 통지를 각각의 패킷으로 송신측에 전달하면 효율성이 저하되기 때문에 두 통지를 한번에 전송할 수 있을 때 보낸다.
- ACK 번호 통지나 윈도우 통지가 연속적으로 발생할 경우 최후의 것만 통지하는 방식으로 패킷을 줄인다.
HTTP 응답 메세지를 수신한다.
- 브라우저가 read 프로그램을 호출한다.
- 프로토콜 스택은 수신 버퍼에서 수신 데이터를 추출하여 애플리케이션에 건네준다.
- 수신한 데이터 조각과 TCP 헤더의 내용을 조사하여 누락을 확인하고 문제가 없을 시 ACK 번호를 반송한다.
- 데이터 조각을 수신 버퍼에 잠시 보관하고 조각을 연결하여 데이터를 원래 모습으로 복원한 후 애플리케이션에 건네준다.
유익한 글이었습니다.