패킷 스위칭
서킷 스위칭을 대체할 신기술로 나온 스위칭 기법이다.
서킷 스위칭은 정보 송수신 간에 회로 연결을 통해 연결을 유지하였다. 이는, 회선을 한 번에 하나의 통신 전용으로 사용해야 했기 때문에 가용성이 좋지 못했다.
패킷 스위치은 회선은 공유하되, 송수신 내용을 패킷이라는 단위로 나누어 저장 후 전달 절차를 사용해 보내는 기법이다.
각각의 데이터들이 패킷으로 묶여있기 때문에 여러명이 동시에 데이터를 수신할 수 있다.
이러한 패킷 스위칭을 구체화한 프로토콜이 점점 거대화되며 오늘날 인터네의 일부가 되었다.(1822 프로토콜)
1822 프로토콜은 긴 세월 동안 계속 진화하여 여러 프로토콜의 형태를 띄게 된다. 그리고 이러한 많은 프로토콜들의 집합을 TCP/IP 스택으로 부르게 된다.
TCP/IP 스택의 계층 구조
tcp/ip 는 각 계층별로 추상화되어 있어 목적에 따라 계층별 프로토콜을 설정하여 데이터 송수신을 연계할 수 있다.
다만, 여러 프로토콜에서 알 수 있듯이 프로토콜의 작성자들마다 설계 철학에 의한 예외가 많다는 문제도 있다.
여기서는 물리, 링크, 네트워크, 전송, 응용 계층으로 나누어 설명한다.
사실 게임 개발자는 거진 응용 계층을 만들지만, 세부적인 네트워킹 최적화를 위해서는 하위 계층에 대해서도 이해하고 있어야한다고 함.
참고로 데이터의 흐름은 송수신 관련 없이 응용>전송>네트워크>링크>물리이다.
물리 계층
물리 계층은 하드웨어 전송을 지원하는 계층이다. 이는 케이블등의 연결 매체를 포함한다. 그리고 전파 역시 정보를 전송하는 물리 매체로 활용된다.
링크 계층
수신, 송신자가 물리 계층을 통해 데이터를 보내거나 받을 수 있도록 돕는 수단이자 역할이다.
링크 계층에서 송수신 단위는 프레임이라고 한다. 호스트들은 링크 계층을 통해 프레임을 주고 받는다.
링크 계층 역할
1. 목적지에 주소를 부여, 각 프레임에 기재한다.
2. 수신 측 주소와 데이터를 담을 프레임 포맷 정의
3. 프레임의 최대 길이를 정의하여 한 번에 데이터를 얼만큼 보낼 수 있는지 윗 계층이 알 수 있게함
4. 물리 계층을 거쳐 들어온 신호를 호스트가 수신 가능토록 프레임을 물리적인 전기신호로 변화하는 방법을 정의해둔다.
링크에서는 프레임이 도착했는지 확인하기위한 시도를 하지 않는다. 이는 비신뢰성 통신임을 의미한다.
물리 계층을 만들기 위한 물리 연결 매체마다, 하나 이상의 프로토콜이 링크 계층에 존재한다.
각각의 물리 연결 매체들은 각각의 링크 프로토콜을 가지지만 데이터 송수신시에는 여러 프로토콜이 두루 사용 가능하다.
위에서 얘기하듯이 TCP/IP 스택은 추상화가 잘되어있다.
여기서는 네트워킹 게임 프로그래머라면 무조건 마주치는 이더넷 프로토콜을 알아본다.
이더넷 -
이더넷은 여러 호스트를 식별하기 위해 매체 접근 제어 주소(MAC) 를 사용한다. MAC 주소는 48비트 숫자로 이더넷 네트워크에 연결 가능한 장비 하나하나마다 고유한 값으로 부여된다. 이러한 장비를 네트워크 인터페이스 컨트롤러(NIC)라고 하며 요즘에는 메인보드에 내장하여 출시한다.
이더넷은 하나의 프로토콜이 아니며 표준 IEEE 802.3 을 기준으로 각각의 물리 연결 매체마다 파생된 이더넷 프로토콜이 많이 있다.
이더넷 링크 계층 프레임을 감싸는 이더넷 패킷은
프리엠블,sfd, 목적지 mac 주소, 발신 mac 주소, 페이로드, 길이/종류, 프레임 체크 시퀀스 등이 포함된다.
이때 이더넷 페이로드의 크기를 1500바이트로 제한하는데, 이렇게 네트워크 통신에서 한 번에 전송할 수 있는 최대 데이터 패킷 크기를 MTU "Maximum Transmission Unit" 라고 한다.
즉, 수신자는 물리계층으로 받은 신호를 데이터화 하여 확인하고 이때, mac주소를 확인 본인이 맞을 시에 페이로드의 데이터를 길이/종류 필드 값에 따라 처리한다.
네트워크 계층
링크 계층의 MAC 주소만으로는 네트워키에 문제가 생긴다. 하드웨어에 직접으로 접근한다는 문제이다.
또한, 각각의 링크 프로토콜들은 서로 이해할수있는 번역 체계가 없다.
링크 계층만으로는 인터넷을 더 작은 네트워크망으로 분리가 불가능하다.
그래서 mac 주소 위에 주소를 하나 더 두어야한다. 각각의 데이터들을 다른 링크 프로토콜이여도 통신이 가능하도록 해야한다. 이 역할을 위해 상위 계층인 네트워크 계층이 있다.
즉, 링크 계층 위에 논리 주소 체계 인프라를 구출하는 역할이다.
IPv4
오늘날 네트워크 계층에 필요한 기능을 구현하는 데 가장 널리 이용되는 프로토콜로 인터넷 프로토콜 버전 4이다.
IPv4의 핵심은 IP 주소이다. IPv4 에서는 IP 주소를 정의하면서 패킷 구조도 정의한다.
IPv4의 패킷에는 헤더 쪽에 네트워크 계층 기능에 필요한 데이터를 담고, 뒤에 윗단 계층의 데이터를 전송할 페이로드가 붙는다.
패킷의 헤더에는
1. 버전 - IPv4 이므로 4
2. 헤더 길이 - 가변적 헤더 길이를 32비트 워드로 표시한다.
3. 서비스 종류 - 혼잡 제어나 서비스 식별자 등 다양한 용도로 사용.
4. 패킷 길이 - 전체 패킷 길이르 바이트 단위로 표시.
5. 분열 식별자, 플래그, 오프셋 - 조각난 패킷을 재조립하느데 사용.
6. TTL - 패킷 전달의 횟수 제한을 의미한다.
7. 프로토콜 - 페이로드 해석을 위한 프로토콜을 나타낸다.
8. 헤더 체크섬 - 헤더의 무결성을 검증하는데 사용하는 체크섬 기록. 페이로드 무결성을 윗단 계층의 역할임.
9. 발신, 목적 주소 - IP 주소
위에서 각각의 링크 프로토콜들이 연결되게 하는 역할을 네트워크 계층에서 한다고 했다.
이는 ARP라고 하는 주소 결정 프로토콜이 그 역할을 한다.
ARP는 쉽게 말해 IP를 MAC 주소로 변환 시키는 프로토콜이다.
링크 프로토콜 간에는 모든 호스트들이 자신의 데이터가 맞는지 확인한다. 이는 큰 문제이다.
두 회사가 협업 할 시 공유되야하는 데이터가 있고 보안되야할 데이터가 있다.
같은 링크프로토콜로만 연결하면 모든 데이터가 양사에 전달되기 때문에 문제가 생긴다.
이를 위해 라우터를 두고 여러 NIC와 IP 주소를 대응하여 지닌다.
A회사에서 데이터를 B회사로 보낼 때 A회사의 IP를 ARP와 이더넷을 이용해 패킷을 이더넷 프레임으로 만든다.
이것을 라우터에게 보낸다. 라우터는 A회사에서 보낸 프레임의 페이로드가 IP 패킷임을 감지하였고, 따라서 라우팅 테이블에서 서브넷 항목을 찾는다.
찾은 서브넷 항목에 따른 NIC 목적지로 라우터는 다시 이더넷 프레임을 만들고 이를 목적지 NIC로 보낸다. 목적지에 도착하면 링크 계층에서 페이로드를 확인하고 이것이 IP패킷임을 확인하고 윗단 계층으로 올린다.
패킷 분열
패킷이 링크 계층의 MTU보다 클 경우 각 링크 프로토콜에 맞는 mtu로 분열시켜 줘야한다. 이를 패킷 분열이라한다.
패킷 분열은 분열식별자, 오프셋, 프래그를 이용하여 같은 패킷인지, 처음 시작과 중간 연결 순서, 그리고 마지막 패킷 조각임을 알 수 있다.
IPv6
IPv4 로 만들 수 있는 고유 IP 주소는 벌써 고갈되었다.
이러한 고갈 문제나 비효율성 해소를 위해 IPv6 가 나왔다. 여기서 기존 ARP 는 NDP가 대체한다.
NDP를 이용해 라우터는 네트워크 접두사와 라우팅 정보를 선전, 호스트는 각자의 IP 주소와 링크 계층 주소를 질의하고 공시한다. 또하느 라우터 레벨에서는 패킷 분열을 지원하지 않기도 한다. 이것은, 모든 분열 관련 필드를 IP헤더에서 제거하여, 패킷의 대역폭을 절약하게 됨을 의미하기도 한다.
전송 계층
원하는 호스트로 패킷을 보냈어도 문제가 생긴다. 만약 호스트가 프로세스를 여러개 가지고 있다면, 적절한 프로세스로 해당 패킹 정보를 보낼수있어야한다. 이 역할을 전송 계층이 한다.
따라서 프로세스를 정하기 위해서 포트라는 개념을 사용한다. 포트는 16비트 숫자로 통신 종단점을 의미한다. 즉, 어떤 프로세스가 특정 포트를 바인딩하면 전송 계층 모듈은 그 포트로 전달되는 데이터들을 해당 포트를 바인딩한 프로세스로 전달한다.
다만, 프로세스들이 같은 포트를 바인딩하지 않도록 포트 번호 등록제를 가진다. 즉, 응용프로그램이 사용할 포트를 정하면 이후에 전송 계층 프로토콜을 통해 실제 데이터를 보내는 것이다. 게임 개발에는 UDP, TCP를 이용한다.
UDP
경량 프로토콜이다. 데이터를 래핑하여 A호스트의 포트에서 다른 호스트의 포트로 데이터를 보내는데 쓴다.
UDP의 데이터그램은 8바이트 헤더와 페이로드를 붙여 만든다.
UDP 는 호스트 간 어떤 공유 상태에도 의존적이지 않다. 우체통에 봉투 넣으면 신경안써도 되는것과 비슷하다.
다만, UDP는 트레픽 제한을 두지도, 데이터를 순서대로 전달하지도, 데이터의 전달을 보장하지도 않는다.
TCP
TCP의 특징은 신뢰성이 있다. 데이터를 순차적으로 전달하려 하며, 따라서 더 큰 헤더를 필요로한다.
수신자는 발신자에게 확인응답ACK를 보낼 수 있다. TCP 의 전송 단위를 세그먼트라고 한다.
TCP에서는 어떻게 신뢰성을 보장할 수 있을까??
송신자는 수신자로부터 ACK를 기다린다. ACK가 일정 시간동안 오지 않거나, 송신자의 상태가 불안정해 ACK를 받을 수 없어 ACK 확인이 안된다면 송신자는 다시 데이터를 수신자에게 보낸다.
이 방식의 기본이 3-WAY 핸드세이킹 절차이다.
먼저 송신자가 시퀀스번호를 임의로 정해 SYN 플래그를 설정하여 데이터를 수신자에게 보낸다.
수신자는 데이터를 받고 시퀀스번호에 1을 더한 값을 ACK로 설정하고 시퀀스번호를 임의의로 정해 SYN플래그를 포함해 보낸다.
송신자는 해당 ACK를 받고 받은 세그먼트의 시퀀스번호에 다시 1을 더해 수신자에게 보낸다. 이때, SYN 플래그를 포함하지 않기 때문에 수신자는 송신자가 ACK를 받았다는 것을 알고 더 이상 송수신하지 않는다.
이 상태에서 문제가 발생할 수 있다. 먼저 TCP는 ACK가 오지 않았다고 전송 멈추지 않는다. 따라서 다음과 같은 문제가 생긴다.
송신자가 컴퓨터가 좋아서 빨리빨리 데이터를 보낸다. 수신자가 데이터를 받지만 수신자 컴퓨터가 좋지 못해 데이터 처리가 느려 ACK가 느려진다. 송신자는 ACK가 안오니까 계속 같은 데이터를 다시 또 보낸다. 여기서 인터넷 자원 낭비와 오버헤드가 야기 된다.
이러한 문제 해결을 위해서 TCP는 흐름 제어 기법을 사용한다.
TCP 세그먼트 헤더에는 수신 윈도필드가 있는데 여기에 수신 가능한 버퍼 여유량을 기재하는 것이다.
수신자는 데이터를 받으면 처리 전까지 버퍼에 데이터를 머무르게 하는데 이 여유량을 기재하는 것이다.
이 기재량에 따라 송신자는 버퍼량에 따라 데이터를 더 보내지 않고 기다릴지 계속 더 보낼지 정한다.
그런데 이러한 하드웨어적인 문제는 해결 가능하지만, 네트워크나 라우터의 성능이 안좋은 것으로 인한 과부하는 막지 못한다. 그래서 TCP는 혼잡 제어라는 기법을 추가로 사용한다.
이 중 두 배 감소 알고리즘은 윈도우 크기를 가변적으로 설정하는 방식이다. 윈도우 크기는 TCP가 한 번에 보낼 데이터양의 크기를 결정하는 매개변수 이다. 만약 패킷 손실이나, ACK 응답이 없거나 너무 느릴경우 이 윈도우 크기를 2만큼 나누어 크기를 줄여 준다. TCP가 보낼 데이터양을 절반으로 줄이니 혼잡을 줄여준다.
응용 계층
TCP/IP스택 최상단 계층이다. 멀티플레이어 게임 코드를 작성할 때, 이곳 응용 계층에 프로그래밍한다.
전송계층과 상호작용한다. 여러 인터넷 기본 프로토콜들이 위치해있다. 몇 가지 확인한다.
DHCP
사설 서브넷 망에 있는 여러 IPv4 주소를 관리하는것은 어렵다. 이것을 자동으로 관리하는 프로토콜이다.
DNS
도메인 네임 시스템 프로토콜은 도메인과 서브도메인 네임을 IP주소로 해석하는데 사용한다.
가령 구글 주소를 IP 주수로 해석하는 프로토콜이다.
네임 서버는 여러 도메인 네임에 대응되는 IP 주소를 가지고 있다. 또한, 본인이 관리하는 도메인이 아니라면 다른 관련 관할 네임 서버를 포인터로 가지고 있어 연결해준다. 그리고 찾은 결과는 캐싱해두어 같은 요청이 오면 빠르게 답한다.
NAT
인터넷 공유기 같은 장비가 있으면 서브넷 전체 호스트를 단 하나의 공인 IP로 연결 가능하다. 이때 사용되는 기술이 네트워크 주소 변환 NAT이다.
공유기에는 인터넷과 연결되는 광역 네트워크 포트WAN과 로컬 네트워크 포트 LAN이라는 NIC가 존재한다.
이때, NAT이 없으면 엄청난 문제가 생기는데 게임기가 게임 서버로 데이터를 보냈다고 치면, 그에 대한 응답을 서버가 게임기에 해야하는데 게임기는 사설 IP 즉, 로컬 IP를 가지고 있다. 그리고 이러한 로컬 IP는 중복된게 정말 많을것이다. 게임 서버는 이융 게임기에 저 사설 IP를 골라서 보낼수없다. 따라서, 잘못된 목적지로 데이터를 보내는 문제가 생긴다.
그래서 NAT을 이용하여 게임기의 IP를 라우터의 WAN IP로 대신하여 보내는것이다.
당연히 다시 받을 때는 라우터가 게임기로 다시 데이터를 보내야하는데 이때, 외부에서 수신한 패킷을 게임기, 휴대폰, 컴퓨터 어디에 전해야 할지 판단하는 메커니즘이 공유기에 있어야한다.
로컬 IP 만으로는 위의 문제를 해결할 수 없기 때문에 포트를 공유기에 기재한다. 즉, 데이터를 보낼때 공유기에 있는 네트워크 주소 변환 테이블에 발신지와 외부 포트, 목적지를 같이 기입한다. 이렇게 하면 포트까지 확인해야하므로 어떤 로컬 기기로 데이터를 전송할지 확인가능하다. 공유기의NAT 모듈은 네트워크, 전송 계층의 경계를 넘나들며 문제를 대응한다.
NAT 투과
그런데 NAT 에는 멀티플레이어 게임 개발자에겐 골치 아프다. A가 NAT A 에 연결되어 있는데 이때, NAT B 에 연결된 B를 초대할 수 없는 것이다. 이는 B가 A에게 패킷을 보내려해도 B의 정보가 A의 NAT 테이블에 없기 때문에 문제가 생기는 것이다.
이것을 NAT 투과라고 한다.
STUN 기법으로 해결한다. 각 플레이어들은 공인 IP로 공개된 중개 호스트, 플레이스테이션 네트워크 서버나 닌텐도 스위치 네트워크 서버 등에 도움을 받는 것이다.
1. A가 중계 서버에 게임 서버를 만든다는 정보를 보낸다. 이러면 NAT A 에 중계 서버의 IP 주소가 저장된다.
2. B는 A의 게임 서버에 참여하겠다는 정보를 중계 서버에 보낸다. 이러면 NAT B 에 중계 서버의 IP주소가 저장된다.
3. 중계 서버는 A 에게 B가 참여한다는 정보를 포함한 패킷을 보낸다. NAT A 는 발신자가 중계 서버인것을 알고 들여보낸다.
4. A 는 B의 정보를 받았으니 B에게 패킷을 하나 보낸다. 허나 NAT B 는 A의 정보가 없으므로 패킷을 폐기한다.
5. 대신 NAT A 의 네트워크 변환 테이블에 B의 주소 정보가 기입된다.
6. 중계 서버는 본인이 가지는 A의 정보를 B에게 알려준다.
7. NAT B 는 중계 서버의 주소를 네트워크 변환 테이블에 저장해두었기에 해당 정보를 받는다.
8. B는 이제 A에게 게임 서버 접속 정보를 보낸다. NAT B 는 A 정보를 알고 있으니 집적 A에게 보낸다.
8. 아까 NAT B 가 A 로부터 받은 패킷을 폐기했지만, NAT A 는 B에게 정보를 보내기 위해 B 의 주소를 네트워크 변환 테이블에 저장해두었다.
9. 그래서 B가 보내는 게임 서버 접속 정보를 NAT A 는 받을 수 있다.
'네트워크 > 멀티 플레이어 게임 프로그래밍' 카테고리의 다른 글
3장 버클리 소켓 정리 (0) | 2024.05.19 |
---|---|
멀티 플레이어 게임 프로그래밍 1장 요약 (0) | 2024.05.03 |