1. 소켓을 작성한다
1. 프로토콜 스택의 내부 구성
- 네트워크 애플리케이션 : 아래로 데이터 송수신 등의 일을 의뢰
- Socket 라이브러리와 그 안에 리졸버가 있음
- OS : 프로토콜 스택
- TCP : 브라우저나 메일 등 일반적인 애플리케이션
- UDP : DNS 서버에 대한 조회 등 짧은 제어용 데이터를 송수신하는 경우
- IP 프로토콜 : 데이터를 패킷단위로 송수신 (ICMP, ARP 프로토콜)
- LAN 드라이버 : LAN 어댑터의 하드웨어 제어
- LAN 어댑터 : 실제 송수신 동작, 즉 케이블에 대해 신호를 송수신하는 동작
2. 소켓의 실체는 통신 제어용 제어 정보
- 프로토콜 스택의 내부에 제어 정보를 기록하는 메모리 영역이 있음
- 통신 상대의 IP 주소, 포트 번호, 통신 동작의 진행 상태 등
프로토콜은 소켓에 기록된 제어 정보를 참조하며 움직임
3. Socket을 호출했을 때의 동작
- 애플리케이션이 소켓을 만들 것을 의뢰하면 프로토콜 스택은 의뢰에 따라 한 개의 소켓을 만듦
- 소켓 한 개 분량의 메모리 영역을 확보
- 생성된 직후의 소켓은 초기 상태임을 나타내는 제어 정보를 소켓의 메모리 영역에 기록
- 다 만든 후 소켓을 나타내는
디스크립터
를 애플리케이션에 알려줌디스크립터
: 프로토콜 스택 내부의 소켓들 중 어떤 건지 알려주는 번호표
2. 서버에 접속한다
1. 접속의 의미
- 소켓을 만든 직후는 상대의 정보를 모르므로 통신을 할 수 없음
- 접속 : 통신 상대와의 사이에 제어 정보를 주고받아 소켓에 필요한 정보를 기록하고 데이터 송수신이 가능한 상태로 만드는 것
- 클라이언트에서
이곳의 IP 주소는 xxx이고 포트번호는 xxx입니다. 데이터 송수신을 하고 싶은데 어떠세요?
라고 정보를 알려 통신하려는 클라이언트가 있다는 것을 서버측에 전달
2. 맨 앞부분에 제어 정보를 기록한 헤더를 배치한다
- 제어정보
- 클라이언트와 서버가 서로 연락을 절충하기 위해 주고받는 정보
- 접속 동작뿐 아니라 데이터를 송수신하는 동작, 연결을 끊는 동작도 포함하여 통신 전체에서 어떤 정보가 필요한지 검토하여 내용을 TCP 프로토콜 사양으로 규정
- 주고받는 패킷의 맨 앞부분에
헤더
를 붙임 (TCP 헤더, 이더넷 헤더, IP 헤더 등)
- 소켓에 기록하여 프로토콜 스택의 동작을 제어하기 위한 정보
- 애플리케이션에서 통지된 정보, 통신 상대로부터 받은 정보 등이 기록됨
3. 접속 동작의 실제
- 먼저 데이터 송수신 동작의 개시를 나타내는 제어 정보를 기록한 헤더를 만듦 (송신처와 수신처의 포트번호를 기록)
- 이를 통해 송신처가 되는 클라이언트 측의 소켓과 수신처가 되는 서버측의 소켓 지정
- 접속해야 하는 소켓이 어느 것인지 확실히 하고 컨트롤 비트인 SYN을 1로 초기화
⇒ 이렇게 TCP 헤더를 만들면 이것을 IP 담당 부분에 건네주어 송신하도록 의뢰
3. 데이터를 송수신한다
1. 프로토콜 스택에 HTTP 리퀘스트 메시지를 넘긴다
- 프로토콜 스택은 받은 데이터를 곧바로 송신하는 것이 아니라 일단 자체의 내부에 있는 송신용 버퍼 메모리 영역에 저장함
- 한 번의 송신 의뢰에서 건네주는 데이터의 길이가 매번 다르므로 어느 정도 데이터를 저장한 뒤 송수신 동작을 함
- 프로토콜 스택은 내부에 타이머가 있어서 일정시간 이상 경과하면 패킷을 송신
- 즉, 데이터가 모이지 않아도 일정 시간이 지나면 데이터를 보냄
⇒ 전자를 중시하면 패킷 길이 ⬆ 네트워크 이용 효율 ⬆ 버퍼에 머무는 만큼 지연 시간 ⬆
⇒ 후자를 중시하면 지연 시간 ⬇ 네트워크 이용 효율 ⬇
2. 데이터가 클 때는 분할하여 보낸다
- 폼을 사용하여 긴 데이터를 보낼 경우 한 개의 패킷에 들어가지 않을만큼 HTTP 메시지가 길어질 수 있음
- 데이터를 MSS의 크기에 맞게 분할해서 한 개씩 패킷에 넣어 송신
MSS
: 헤더를 제외하고 한 개의 패킷으로 운반할 수 있는 TCP 데이터의 최대 길이
3. ACK 번호를 사용하여 패킷이 도착했는지 확인한다
시퀀스 번호
: 데이터를 조각으로 분할할 때 조각이 통신 개시부터 몇 번째 바이트에 해당하는지를 세어둔 것, 악의적인 공격을 방지하기 위해 초기값을 난수값으로 설정 (SYN이 1이라는 것을 통해 초기값임을 인지)- 수신측에서는
패킷 전체 길이 - 헤더 길이
와시퀀스 번호
를 비교해서 패킷 누락 검증 - ACK 번호 : 수신 확인 응답, 어디까지 수신했는지를 송신측에 알려주기 위한 용도
⇒ TCP는 이 두 가지를 이용해 데이터를 받은 것을 확인하고 확인할 때까지 송신한 패킷을 송신용 버퍼 메모리 영역에 보관해 둠
- 송신한 데이터에 대응하는 ACK이 오지 않으면 패킷 재전송
- 서버가 다운되는 등 아무리 보내도 데이터가 도착하지 않는 경우, TCP는 몇 번 다시 보낸 후 전망이 없는 것으로 보고 송신동작을 강제종료하고 애플리케이션에 오류 통지
4. 패킷 평균 왕복 시간으로 ACK 번호의 대기 시간을 조정한다
- 타임아웃 값 : ACK 번호가 돌아오는 것을 기다리는 시간
- TCP는 대기시간을 동적으로 변경하는 방법을 사용
- 대기시간 ⬆ : 패킷을 다시 보내는 동작도 지연되어 속도 저하
- 대기시간 ⬇ : ACK 돌아오기 전에 다시 보내야 하므로 낭비
5. 윈도우 제어 방식으로 효율적으로 ACK 번호를 관리한다
- 한 개의 패킷을 보내고 ACK을 기다리는 시간이 낭비이므로 TCP는
윈도우 제어
라는 방식을 이용해 송신과 ACK 번호 통지의 동작 실행 윈도우 제어
: 한 개의 패킷을 보낸 후 ACK 번호를 기다리지 않고 차례대로 연속해서 복수의 패킷을 보내는 방법- 수신측의 능력을 초과해서 데이터를 송신하는 사태를 방지하기 위해 수신측에서 송신측에 수신 가능한 데이터 양(
윈도우 사이즈
)을 통지 후 수신측은 이 양을 초과하지 않도록 송신 동작 실행
- 수신측의 능력을 초과해서 데이터를 송신하는 사태를 방지하기 위해 수신측에서 송신측에 수신 가능한 데이터 양(
6. ACK 번호와 윈도우를 합승한다
- 윈도우 통지 : 수신측이 수신 버퍼에서 데이터를 추출하여 애플리케이션에 건네주었을 때
- 수신측에서 애플리케이션에 데이터를 건네주고 수신 버퍼의 빈 영역이 늘어났을 때
- ACK 번호 통지 : 수신측에서 데이터를 받았을 때 내용을 조사하여 정상 수신을 확인할 수 있는 경우에만
- 즉, 데이터를 수신한 후 즉시
- 두 가지를 매번 따로따로 보내면 효율성이 저하됨 ⇒ 바로 보내지 않고 잠시 기다려서 동시에 일어난다면 두개를 한 패킷에 합승시키는 방식으로 패킷의 수를 줄임
- ACK 통지가 연속하여 일어나면 최후의 것만 통지
- 윈도우 사이즈 통지 역시 연속해서 일어나면 최후의 것만 통지
7. HTTP 응답 메시지를 수신한다
- 브라우저는 Request 메시지 송신을 끝낸 뒤, Response 메시지를 받기 위해 read 호출
- 프로토콜 스택은 수신 버퍼에서 수신 데이터를 추출하여 애플리케이션에 건네줌
- 응답이 돌아올 때까지 잠시 보류
- 서버에서 응답 메시지의 패킷이 도착했을 때 그것을 수신하여 애플리케이션에 건네주는 작업 재개
4. 서버에서 연결을 끊어 소켓을 말소한다
1. 데이터 보내기를 완료했을 때 연결을 끊는다
- 데이터 보내기를 완료한 쪽에서 연결끊기 단계에 들어감
- 과정 (ex. 서버측)
- 서버측의 애플리케이션이 먼저 close를 호출
- 서버의 프로토콜 스택이 FIN(1) 을 송신
- FIN을 받은 클라이언트는 잘 받았다는 ACK번호를 서버에 반송
- 클라이언트 측 애플리케이션이 close 호출
- 클라이언트 프로토콜 스택이 FIN(1) 을 송신
- FIN을 받은 서버는 잘 받았다는 ACK번호를 클라이언트에 반송
- 대화 종료
2. 소켓을 말소한다
- 대화가 끝나면 소켓을 사용하여 대화할 수 없으므로 소켓은 필요 없지만, 오동작을 막기 위해 잠시 기다린 후 소켓 말소
- 오동작의 예 : FIN을 받은 클라이언트가 ACK을 보냈는데 돌아오지 않아 다시 FIN을 보내려고 하면 소켓이 이미 말소되고 없어서 새 소켓에 FIN이 도착할 수 있음
- 기다리는 시간은 패킷을 다시 보낼 때 기다리는 시간만큼 기다림, 보통 몇 분 정도
3. 데이터 송수신 동작을 정리한다
- 소켓 작성
- 서버측에서 애플리케이션이 동작하기 시작했을 때 소켓을 만들고 접속 대기 상태로 만듦
- 접속
- 클라이언트에서 서버를 향해 접속 동작 실행
- 클라이언트에서 서버에게 SYN(1)과 시퀀스 번호 초기값, 윈도우 값 보냄
- 서버는 잘 받았다는 ACK 번호와 윈도우 값, SYN(1), 시퀀스 번호 초기값 보냄
- 클라이언트에서 잘 받았다는 ACK 번호를 보냄
- 송수신 동작
- TCP는 클라이언트가 보내는 리퀘스트 메시지를 조각으로 분할 후 헤더(시퀀스 번호)를 붙여서 보냄
- 서버는 잘 받았다는 ACK 번호와 변경된 윈도우 값 보냄
- TCP는 서버가 보내는 리스펀스 메시지를 조각으로 분할 후 헤더(시퀀스 번호)를 붙여서 보냄
- 클라이언트는 잘 받았다는 ACK 번호와 변경된 윈도우 값 보냄
- 연결 끊기
- 서버에서 FIN(1)을 보냄
- 클라이언트에서 ACK 번호를 보냄
- 클라이언트에서 FIN(1)을 보냄
- 서버에서 ACK 번호를 보냄
5. IP와 이더넷의 패킷 송수신 동작
1. 패킷의 기본
- 패킷 = 헤더 + 데이터
- 헤더
- MAC 헤더 : 이더넷용 헤더 (서브넷 안에 있는 이더넷이 중계 장치까지 패킷을 운반)
- IP 헤더 : IP용 헤더 (IP가 목적지를 확인하여 다음 IP의 중계 장치를 나타냄)
- 송신처에서 목적지 액세스 대상 서버의 IP주소를 IP헤더에 기록
- IP는 이를 통해 수신처가 어느 방향에 있는지 조사 후 그 방향에 있는 다음 라우터의 이더넷 주소(MAC주소)를 MAC 헤더에 기록
- 허브에서 이더넷용 표와 헤더의 수신처 정보를 결합해 여러 허브를 순차적으로 경유한 뒤 다음 라우터에 도착
- 라우터에서 IP용 표와 IP 헤더의 수신처 정보를 결합해 다음 라우터를 판단하고 다음 라우터 주소를 MAC 헤더에 기록 후 다음 라우터에 송신
- 이것을 반복하면 패킷은 목적지에 도착
2. 수신처 IP 주소를 기록한 IP 헤더
- IP 주소로 표시된 목적지까지 패킷을 전달할 때 사용하는 제어 정보
- IP 담당 부분은 TCP로부터 TCP 헤더와 데이터 조각이 오면 IP 헤더를 만들어 TCP 헤더 앞에 붙임
- 수신처 IP 주소 : TCP 담당 부분에서 통지된 통신 상대의 IP 주소 (애플리케이션이 통지)
- 송신처 IP 주소 : 송신처가 되는 LAN 어댑터를 판단하여 주소 설정
- 프로토콜 번호 : 패킷에 들어간 내용물이 어디에서 의뢰받은 것인지를 나타내는 값
3. ARP 프로토콜
- ARP : IP 주소로 MAC 주소를 찾아주는 프로토콜
- 이더넷에 연결된 라우터들에게 브로드캐스트하는 방식으로 MAC 주소를 알아냄
4. 이더넷용 MAC 헤더
- 이더넷 등의 LAN을 사용하여 가장 가까운 라우터까지 패킷을 운반할 때 사용하는 제어 정보
- IP 담당 부분은 MAC 헤더를 만들어 IP 헤더 앞에 붙임
- 수신처 MAC 주소 : 패킷을 건네주는 상대의 MAC 주소
- 송신처 MAC 주소 : 송신한 측의 MAC 주소, 자체 LAN 어댑터의 MAC 주소
- 이더 타입 : 사용하는 프로토콜의 종류
5. 이더넷
- 이더넷 : 다수의 컴퓨터가 여러 상대와 자유롭게 적은 비용으로 통신하기 위해 고안된 통신 기술
- 성질
- 수신처 MAC 주소에 따라 패킷이 누구에게 갈 것인지를 앎
- 송신처 MAC 주소에 따라 누가 송신한 것인지를 앎
- 이더 타입에 의해 패킷의 내용물로 무엇이 들어있는지를 앎
6. 패킷에 3개의 제어용 데이터 추가
- 프리앰블
- 스타트 프레임 딜리미터
- 프레임 체크 시퀀스(FCS) : 오류 검출용 데이터
- 패킷을 운반하는 도중에 잡음 등의 영향으로 파형이 흐트러져 데이터가 변한 경우를 검출하기 위해 사용
- 32비트의 비트열로, CRC(Cyclic Redundancy Check)를 바탕으로 계산한 것
- 계산한 결과와 일치하는지를 통해 데이터 변화한 사실 검출
7. 허브
- 리피터 허브 : 반이중 모드
- 어떤 시점에서 송신과 수신 중 한쪽만 가능한 것
- 스위칭 허브 : 전이중 모드
- 송신 동작과 수신 동작을 동시에 병행하여 실행할 수 있는 것
6. UDP 프로토콜을 이용한 송수신 동작
1. 수정 송신이 필요없는 데이터의 송신은 UDP가 효율적이다
- TCP
- ✅ 데이터를 확실하면서도 효율적으로 전달
- ❌ 구조가 복잡함
- 데이터를 한 번에 다 보내고 수신 확인 응답을 한 번만 받는 방법
- UDP
- 수신확인이나 윈도우가 없어서 데이터 송수신 전 제어정보를 주고받을 필요가 없음
- 접속이나 연결 끊기 단계가 없음
- IP헤더의 IP주소와 UDP 헤더의 포트 번호를 결합하여 상대 찾음
- ✅ 송수신 간단
- ❌ 데이터 안정성이 보장되지 않음
- UDP 헤더
- 송신처 포트 번호
- 수신처 포트 번호
- 데이터 길이
- 체크섬 : 오류 유무를 검사
2. UDP를 사용하는 경우
- 수신확인이 안 오면 전부 다 다시 보내기 때문에 보내려는 패킷이 적은 경우는 효율적
- DNS 서버에 대한 조회 등 제어용으로 실행하는 정보 교환
- 데이터의 손실보다 속도가 더 중요한 경우
- 음성이나 영상 데이터는 정해진 시간 안에 데이터를 건네주어야 하므로 빠른 UDP를 사용