[Network Programming with Rust] Week 1
Study/Network Programming with Rust

[Network Programming with Rust] Week 1

반응형

Chapter 1. Introduction to Client/Server Networking

 

1. A brief history of networks

진화된 통신 수단. 새로운 통신 수단으로 컴퓨터가 대두됨. 컴퓨터끼리의 통신이 점차 커져 하나의 거대한 네트워크가 구성될 수 있었음.

지리적 관점에서 구성되기도 하는데 지역에 따라 구분하면 LAN(Local Area Network), 이런 LAN이 뭉치게 되면 WAN(Wide Area Network)가 된다.

 

2. Layering in networks

컴퓨터 과학에서는 종종 하나의 문제를 작게 쪼개어 본다. 이제 필요한 건 큰 문제를 해결하기 위해 쪼개진 문제들의 해결책들을 잘 조화시켜 만들어낸 규칙들의 집합이다. 이 규칙들의 집합을 사전에 약속된 포맷과 함께 프로토콜(protocol)이라고 한다.

네트워크에서도 이런 프로토콜을 적용해서 표준을 만들려는 시도가 있었는데 그 결과로 나온 것이 바로 OSI Model이다. 총 7 계층(7 Layer)으로 이루어져 있고 다음과 같은 형태를 가지고 있다.

낮은 계층부터 높은 계층까지 순서대로 Physical, Data Link, Network, Transport, Session, Presentation, Application Layer다. 각 계층에 대한 설명은 위키피디아에서 보는 것으로 대체한다.

OSI Model이 표준화되는 와중에, Defense Advanced Research Projects Agency (DARPA)가 더 간단한 TCP/IP Model을 모두 구현해내기 위해 등장했다. 낮은 계층부터 순서대로 Hardware interface, IP, Transport, Application Layer다.

위의 두 모델 모두 자신의 바로 옆에 있는(위아래) 계층의 데이터를 다룬다. 그리고 데이터들은 Protocol Data Unit (PDU)로 불린다. PDU들은 계층을 내려갈 때마다 헤더에 추가적인 데이터가 붙게 되고 이 과정을 encapsulation이라 한다.

가장 성공적인 네트워킹 방식은 Ethernet이었다. 낮은 코스트와 유지보수가 쉽다는 장점을 가지고 있었기 때문이었다. 통신 방식은 공유 미디어 프로토콜에 frame을 뿌려 자신에게 온 것을 받아들이고 아닌 것은 버리는 식으로 동작한다. 하지만 전송 도중에 미처 도달하지 못해 손실이 발생할 수도 있다. 이 경우에 손실을 인지한 host가 다른 hosts에게 collision이 일어났다는 것을 알려준다. 그리고 얼마간의 시간이 지난 후 다시 전송을 시작하려 하는데 만약 정해진 횟수만큼의 시도만큼 실패하게 된다면 전송을 포기하게 된다.

이러한 통신 방식을 Carrier-Sense Multiple Access with Collision Detection (CSMA/CD)라고 한다. 이 프로토콜의 단점이라고 한다면 Ethernet이 가지는 연결 가능한 거리가 비교적 짧다는 것에 있다. 그래서 하나의 큰 네트워크에 다수의 세그먼트들의 연결되어야 한다. 연결을 위해서는 두 개의 인접한 Ethernet segments가 두 개의 스위치(장비)를 이용한다. 서로 다른 collision domain을 가지고 있으니 collision 될 확률도 낮출 수 있다.

 

3. Addressing in networks

패킷을 전달하는 데에 있어 신뢰성을 높이기 위해서는 host와 network를 식별하는 것은 중요하다. 네트워크의 규모에 따라 3가지 주요 요소가 이를 식별하는 데에 쓰인다. 한 가지 흥미로운 점은 특별한 사용을 위해 예약된 주소가 모드마다 하나 이상 존재한다는 것이다.

  • Ethernet adderss (a.k.a MAC; Media Access Control)
    : 48-bit의 크기를 가지며 네트워크 장비마다 다르게 할당된다. 특별히 예약된 비트로는 첫 번째 옥텟의 LSB(Least Significant Bit)를 설정하는 것이다. 1이면 멀티캐스트, 0이면 유니캐스트로 동작한다.
  • IP address
    : 1980년대에 등장한 32-bit의 표준은 IPv4다. 하지만 1995년에 모든 디바이스에게 할당하기에는 불충분한 크기였다는 것이 분명해졌다. 이는 IPv6의 개발 배경이 되었고 그 크기는 128-bit로 확장되었다. 그리고 IPv4는 기존의 클래스 기반 주소 사용 대신에 클래스 없이 표현하는 CIDR을 사용하게 바뀌었다. 예약된 주소 중 일부로는 192.169.0.0 ~ 192.168.255.255가 있는데 개인 주소로 사용하도록 예약된 구간이다. Internet Assigned Numbers Authority (IANA)는 회사에게 공식적인 라우팅 IP 주소 블록을 할당해준다.
  • Autonomous system number
    : Autonomous System (AS)에 유니크하게 사용되는 32-bit 숫자다. IP 주소처럼 IANA이 할당하고 관리한다.

이외에도 프로세스끼리 port를 통해 커뮤니케이션을 할 수 있다. 특정 port를 한 프로세스에게 할당해주고 패킷이 그 포트로 오면 그 프로세스에게 넘겨주는 식이다.

 

4. How IP routing works

기본적인 IP의 동작 방식은 구글링을 통해 여러 블로그와 위키피디아 등을 통해 잘 설명되어 있다. 그래서 참고하면 좋을만한 링크를 몇 개 남기는 것을 대신한다.

https://en.wikipedia.org/wiki/IP_address

 

IP address - Wikipedia

From Wikipedia, the free encyclopedia Jump to navigation Jump to search Numerical label used to identify a network interface in an IP network An Internet Protocol address (IP address) is a numerical label such as 192.0.2.1 that is connected to a computer n

en.wikipedia.org

https://www.sangoma.com/how-ip-routing-works/

 

How IP Routing Works ⋆ Sangoma

Wondering how IP routing works? IP routing refers to protocols that determine how data travels over a network from one host to another through a series of routers. Learn more about IP routing.

www.sangoma.com

https://www.cloudflare.com/ko-kr/learning/network-layer/what-is-routing/

IP의 관점에서 흥미로운 점은 Time To Live (TTL)을 사용한다는 것이다. 이것은 라우팅에 있어서 hop limit을 정한 것이다. 패킷에 기록된 TTL의 수만큼 라우터를 거칠 수 있다. 라우터는 패킷을 만날 때마다 해당 값을 줄인다. 만약 0이라면 그 패킷을 버린다. 라우터 사이에서 무한 루프를 돌지 않도록 하기 위해 만든 메커니즘이다. 참고로 패킷을 드롭하는 이런 경우가 발생할 경우, 라우터는 Internet Control Message Protocol (ICMP)을 이용해서 error를 돌려준다.

만일 TTL 횟수 안에서 어떤 라우터가 보유한 라우팅 테이블에서 prefix 검사를 했는데 다수의 루트가 매치되는 경우에는 어떻게 동작할까? 이럴 때 라우터는 특정 루트를 확정해서 포워딩해야만 한다. 다수의 루트 중에서 선택하는 기준은 매칭 했을 때 가장 긴 prefix를 가지는 경우다.

위에서 언급된 IP routing의 특징은 IPv6에서도 별반 다르지 않다.

여기서 궁금한 점이 생길 수 있다. 라우터는 어떻게 라우팅 테이블을 구성하는지에 대한 것이다. 항상 그렇듯이 이를 도와주는 프로토콜이 존재한다. 라우팅 프로토콜에는 크게 2가지 종류가 있다: 내부 게이트웨이 프로토콜(내부에서 사용하는 자율 시스템(AS) 간의 라우팅에 사용), 외부 게이트웨이 프로토콜(외부의 자율 시스템(AS) 간의 라우팅에 사용 / 예를 들어 BGP가 있음).
내부 게이트웨이 프로토콜은 다시 크게 2가지 종류가 있다. 1) RIP(Routing Information Protocol) - 연결 상태 기준. 각 라우터는 전체 네트워크 토폴로지 관점에서 유지된다. / 2) OSPF(Open Shortest Path First) - 거리 백터 기준. 각 라우터는 주변에 존재하는 단 하나의 홉의 거리만큼의 이웃(라우터)만을 알고 있다. 자세한 내용은 이 책에서 후술 할 예정이다. 중요한 건 라우터끼리도 라우팅 프로토콜을 통해 정보를 교환한다는 것이며, 물론 이를 통한 패킷들도 프로토콜에 따른 encapsulation이 진행된다.

그래도 라우팅 프로토콜이 궁금해서 대충이라도 미리 알고 싶은 사람들을 위해서 아래 링크를 남겨둔다.
https://needjarvis.tistory.com/159

 

라우팅 프로토콜(Routing Protocol)

라우팅(Routing)이란? Routing이란 패킷(Packet)을 전송하기 위한 수많은 경로 중에서 한 가지 경로를 결정하는 것이다. 라우팅에는 동적 라우팅(Dynamic Routing)과 정적 라우팅(Static Routing)으로 나누는데.

needjarvis.tistory.com

 

5. How DNS works

인터넷 상에 존재하는 모든 서비스를 조회하기 위해 일일이 IP 주소를 외우고 다니는 것은 불가능한 일이다. 그래서 이를 위한 프로토콜이 존재하는데 바로 Domain Name Server(DNS)다. DNS sever에는 IP 주소에 사람이 읽을 수 있는 이름과 매핑시켜놓은 데이터베이스를 가지고 있어서 'www.google.com'과 같은 주소로 접속을 시도하면 데이터베이스에서 조회하고 결과를 돌려준다. 아래의 그림은 가지고 있는 데이터베이스에 원하는 결과가 없을 때 동작하는 순서다.

https://www.cloudflare.com/ko-kr/learning/dns/what-is-dns/

현재 우리가 배우고 있는 챕터의 서론에서 말했다시피 Linux를 기준으로 설명한다. 리눅스에서 돌아가는 애플리케이션이 이름을 통해 IP를 얻기(영어로는 resolving a name) 위해서는 'getaddrinfo'와 같은 시스템 콜을 사용하면 된다. 어떤 스텝을 밟는지 살펴보자.

  1. 일반적으로 각 컴퓨터 내부에는 /etc/resolv.conf 파일에 존재하는 local DNS server를 가지고 있다. 그리고 대부분은 ISP의 DNS server 주소를 가리키고 있다. 집 와이파이의 DNS server도 포함해서 말이다. 이 경우, DNS는 있는 그대로 ISP의 DNS server에게 요청한다. 그럼 OS는 주어진 name의 IP를 서버에 물어본다.
  2. local DNS server는 host로부터 받은 질문을 미리 알고 있는 Root name server 리스트에게 보낸다. 이 서버는 국제 인터넷 주소 관리기구(Internet Corporation for Assigned Names and Numbers, ICANN)에 의해 관리되고 잘 알려져 있다. 또한 Root name server는 Top Level(name의 .com 같은 부분) 도메인을 알고 있는 서버를 저장하고 있다.
  3. Root name server는 요청받은 name과 맞는 TLD (Top-Level Domain) name servers를 리턴한다.
  4. local DNS sever는 받은 TLD 서버 리스트 중에 한 곳에 다시 같은 질문을 한다.
  5. TLD name serever는 'google.com' 도메인에 해당하는 name servers를 리턴한다. 'google.com' 도메인의 관리자는 여러 이 도메인의 여러 name server를 가지고 있다. 그래서 이 서버들은 해당 도메인의 레코드에 대해 모든 권한을 가지고 있으며 각 레코드는 authoritative라고 마킹되어 있다.
  6. local DNS server는 받은 리스트에서 서버 하나를 골라서 또 같은 질문을 던진다.
  7. 질문을 받은 서버가
    1) 알고 있다면 response를 준비하고 authoritative로 레코드에 마킹하고, local DNS server에게 'www.google.com'의 address를 돌려준다.
    이 결괏값은 수명이 존재해서 local DNS server는 나중에 사용하기 위해 캐싱하고 주어진 시간 끝나면 결괏값 버릴 수 있다.
    2) 알지 못한다면 NXDOMAIN (Non-eXistent DOMAIN)이라는 특별한 response를 돌려보낸다. 물어본 도메인 네임이 전혀 존재하지 않는다는 의미다.
  8. local DNS server는 해당 질문을 한 OS에게 같은 response를 돌려준다.

DNS는 주변 친구들에게 누군가의 주소를 물어보는 것과 같다. 그리고 DNS는 transport layer에서 그리 높은 신뢰성이 필요 없기 때문에 UDP를 사용하는 게 좋아 보이지만, 대부분의 구현에서는 통신이 굉장히 불안정한 경우 TCP로 이어지도록 옵션을 넣어놨다.

 

6. Common service models

6.1 Connection-oriented service

connection-oriented service는 실제로 데이터를 보내기 전 가상의 연결을 만드는 setup process가 존재한다. TCP가 현대 네트워크에서 보이는 대표적인 예시다. TCP의 PDU는 세그먼트(segment)라고 하며 header section과 data section으로 구성되어 있다.

https://en.wikipedia.org/wiki/Transmission_Control_Protocol

 

Transmission Control Protocol - Wikipedia

From Wikipedia, the free encyclopedia Jump to navigation Jump to search Principal protocol used to stream data across an IP network The Transmission Control Protocol (TCP) is one of the main protocols of the Internet protocol suite. It originated in the in

en.wikipedia.org

> TCP header

https://en.wikipedia.org/wiki/Transmission_Control_Protocol

  • Control bits
    : 9-bit로 이루어져 있다. 유심히 봐야 할 것은 SYN, ACK, FIN, RST이다.
    SYN - 동기화 시퀀스 번호. 양쪽이 보낸 가장 최초의 패킷에만 이 플래그를 설정해야 한다.
    ACK - 세팅되어 있다면, 수신자에게 Acknowledgement number 필드가 중요하다는 것을 알려준다.
    FIN - 연결을 끊기 시작할 때 세팅.
    RST - 에러 때문에 연결을 리셋해야 할 때 세팅.
  • Sequence number
    : 32-bit로 이루어져 있는데 수신자가 받은 패킷을 재 정렬하기 위해 사용한다.
    SYN flag가 세팅되어 있다면 현재 값이 첫 시퀀스 번호다. 세팅되지 않았다면 지금까지 쌓인 시퀀스 번호다.
  • Ackowledgement number
    : ACK flag가 세팅되어 있다면 현재 값은 수신자가 예상하는 다음 시퀀스 번호를 나타낸다.

 

TCP를 통해 데이터를 교환하기 전에 두 hosts는 반드시 3-way handshake를 통해 연결돼야 한다.

https://mindnet.tistory.com/entry/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-22%ED%8E%B8-TCP-3-WayHandshake-4-WayHandshake

이 모델의 장점은 양쪽 모두가 신뢰성 있는 연결을 가질 수 있다는 것이다. 반대로 단점은 이렇게 하는 것만으로 큰 비용이 발생한다는 것이다. 패킷 하나를 전송하는 데에 100ms가 걸린다고 가정하면 위의 과정을 끝마치기 위해 최소한 3개의 패킷이 교환되어야 하며 같은 말로 최소 300ms 만큼의 딜레이가 생긴다는 것이다. 그다지 큰 문제로 안 보일지 몰라도 하나의 노트북이 페이스북을 사용할 때 서버를 여는데 수천 번의 연결이 있을 것인데 이럴 때는 매우 큰 문제가 될 수 있다.

Connection-oriented 모델은 괜찮아 보이지만 몇몇 경우에는 중요할 수도 있고 불필요할 수도 있는 오버헤드가 존재한다. 예를 들어 비디오 스트리밍 서비스 같은 경우가 있다. 스트리밍을 할 때에는 몇몇 패킷을 잃어버리는 것은 큰 문제가 되지 않는다. 이런 경우 Connectionless 모델이 더 좋을 것이다.

6.2 Connectionless service

이름에서부터 알 수 있듯이 상대방과의 연결을 보장하지 않은 채로 데이터를 보내는 프로토콜이다. UDP가 그중 하나이며 checksum field를 제외하고는 데이터의 correctness는 보장하지 않는다.

> UDP header

https://en.wikipedia.org/wiki/User_Datagram_Protocol

복잡했던 TCP header보다 간결한 모습을 보여준다. 얼마나 간결하냐면 패킷의 순서를 알려주는 필드조차 존재하지 않는 것을 확인할 수 있다. 간단한만큼 위에서 설명한 여러 사항을 보장해주지 못한다.

 

7. The network programming interface in Linux

Linux에서 glibc와 함께 네트워크 프로그래밍을 어떻게 구현하는지 살펴본다.

OS가 제공하는 가장 중요한 네트워킹 primitive는 socket이다. socket이란 Unix-like OS에서 각 파일마다 부여된 특별한 ID, 즉 file descriptor를 말한다. I/O와 관련된 시스템 콜을 통해 구현할 수 있다.

* 위에 소개된 모든 시스템 콜을 다 정리하기엔 양이 방대하고 구글링만으로 쉽게 정보를 알 수 있기 때문에 생략함 *

저자가 구현한 socket programming을 소개하는 것으로 예제를 대체한다.

https://github.com/TwoPair/C-Playground/tree/main/socket

 

GitHub - TwoPair/C-Playground: C Programming Practice

C Programming Practice. Contribute to TwoPair/C-Playground development by creating an account on GitHub.

github.com

그런데 위에 소개된 시스템 콜들은 대부분 blocking 방식(두 hosts 중 한쪽의 일이 모두 끝나야지 다른 한쪽에서 접근할 수 있는 방식)이다. 멀티스레드를 지원하는 현대에서는 바람직하지 않다. 그래서 Unix에서 asynchronous(비동기), non-blocking 방식을 제공하는 시스템 콜 또한 존재한다.

  • select system call
    : 주어진 sockets 리스트를 모니터링하면서 읽을 데이터를 가지고 있는지 caller에게 알린다.
  • poll system call
    : select와 비슷하지만 좀 더 높은 semantic을 가지고 있다. sockets 리스트와 더불어 timeout이 존재한다. 비동기적으로 socket의 timeout을 감시하면서 데이터를 가지고 있다면 caller에게 알린다.

두 시스템 콜은 유용하지만 실제로는 많은 소켓들을 감시하기 때문에 매우 느리다. 이를 해결하기 위해서는 외부 라이브러리를 이용해야만 해결할 수 있다.

 

위의 도식에서 TCP를 기준으로 사용된 시스템 콜들과 시간대별로 설정되는 state들을 확인할 수 있다.

 

* blocking, non-blocking / synchronization, asynchronization에 대한 이해

https://deveric.tistory.com/99

 

동기/비동기와 블로킹/논블로킹

동기, 비동기 그리고 블로킹, 논블로킹은 프로그램을 개발할 때 중요한 개념 중 하나입니다. 기초 프로그래밍을 배우고 응용 파트인 병렬 프로그래밍을 익힐 때 나오는 개념이고 익히기 쉽지 않

deveric.tistory.com

반응형