L4에 대한 정리2

2021. 10. 31. 23:23게임서버/TCP IP 이론

320x100

안녕하세요 대학생개발자입니다.

이번글에서는 L4에 대한 정리를 또 해보려고 합니다.

 

저번글에서는 거의 TCP에 대한 얘기를 주로 했었었습니다.

UDP에 대한 아주 짧은 내용과함께요.

이번 글에서는 TCP에 이어서 UDP에 대한 내용을 좀 정리하며 L4를 마무리 해볼까 합니다. 

 

뭐.. 다들 아시겠지만 L4 스위치에는 공유기가 있습니다.

공유기가 어떻게 L4 스위치 역할을 하는가...

저는 사실 공유기는 L3기기인 줄 알고 있었는데 L4기기인 것 같더라구요.

왜냐면 공유기는 IP도 변경하지만 포트까지 변경해버리기 때문에 L4기기가 맞습니다.

 

우리가 데이터를 내보내면 공유기는 내부에서 dynamic port forwarding table을 만들어서 거기에 자신의 공인 아이피:포트 와 사설 아이피(호스트):포트를 서로 맵핑을 해놓는 거죠.

 

예를 들면 이런 식 일 겁니다.

 

192.168.0.5:8888 <- 사설 아이피를 가진 호스트

10.2.59.7<- 공인 아이피를 가진 공유기

 

이 둘을 하나로 묶어서 처리를 하는 거죠.

공유기가 가진 포트 중 하나를 내부에 있는 사설망 속 호스트의 아이피와 호스트로 묶어버리겠다는 의미가 되겠죠.

그렇기 때문에 내가 데이터를 내보내게 되면 공유기는 내가 보낸 데이터중 L3의 헤더와 L4의 헤더를 까서 공유기 자신의 아이피를 넣고 보내버린답니다.

반대로 들어올 때는 공인 아이피+포트를 사설 아이피 + 포트로 바꿔버려서 전달해준다고 합니다.

 

ㅋㅋㅋ 신기하네요 중간에서 전달자 역할을 하는 하는 거긴 한데요

이런 식으로 우리 공유기는 동적으로 포트 포워딩을 통해서 연결을 한답니다.

하지만 예전같은 경우 p2p게임일때는 이런게 안되었다고 하는데요.

이유가 내가 방을 열어도... 내 아이피는 사설망의 아이피와 포트이기 때문에 사실상 그 누구도 접근을 할 수가 없었다고해요 그래서 포트포워딩 혹은 DMZ 기능을 사용하라고 하는데요.

 

포트 포워딩의 경우에는 내 아이피와 포트를 공유기의 공인 아이피와 포트번호로 맵핑을 시켜서 그 포트로 들어오는 것은 나에게로 보내달라 라는 것이 되는 거구요.

DMZ는 포트를 연다는 점에서는 비슷하지만 하나의 포트가 아닌 공유기로 들어오는 모든 포트를 내 호스트로 보내달라는 의미가 되므로 모든 포트에 대해서 다 열려버리게 되는 것입니다.

그러므로 위험해요.

그래서 저는 비추하고 있습니다.

이유는 조만간 정리하게될 L4스위치의 목적하나인 NAT방화벽 기능이 상실되게 때문입니다.

 

넵 그러면 여기서 공유기의 기능을 하나 알 수 있어요.

내가 오픈하지 않은 포트로 들어오는 데이터는 공유기 선에서 걸러버린다가 되는 거겠죠.

즉 하나의 물리적인 방화벽이 만들어진다는 것입니다.

네 그렇다고요.

이름은 NAT인데요 netork address translate라고 합니다.

접근을 못하게 하기 위해서 다른 망으로 구분을 지어서 입장 가능한 문을 통해서만 입장할 수 있게 하는 방식입니다.

 

음.... 되게 뭔가 고민을 해서 쓰려고 했는데 제가 뇌가 지워졌는지 뭐가 생각이 잘안납니다...

이 내용은 추후에 수정을 통해서 보강해놓도록 하겠습니다...ㅠㅠ

 

다음으로는 RUDP에 대해서 좀 얘기를 해볼 건데요.

사실 RUDP란 것은 UDP + TCP의 기능인데...

그럴 거면 TCP가 낫지 않냐는 의견을 가지신 분들이 꽤나 있으십니다.

하지만 RUDP는 내가 조종이 가능한 TCP의 형태인 반면 TCP는 너무 과하게 친절하고 과하게 조심성이 강합니다.

그렇기 때문에 현업에서는 RUDP를 많이 쓰고 있다고 합니다.

 

UDP는 TCP와 많이 다르죠.

일단 단일 연결이라는 개념이 없습니다.

TCP는 아이피와 포트가 매핑이 되어있어서 아무리 다른 곳에서 데이터를 보낸다고 한들 L4에서 걸러버릴 테니까요.

하지만 UDP는 그렇지 않죠.

따로 저장을 해두지 않으니까요.

그냥 그 포트와 그 아이피로 들어오는 건 무조건 내 거입니다.

그래서 L4의 수신 버퍼에 잘 가져다 놓죠.

 

그런 점을 이용해서 사실 UDP는 예전에 P2P 게임에서 많이 사용했었습니다.

일단 클라이언트를 켜게 되면 임시로 아이피와 포트만 저장을 담당하는 서버로 연결을 요청하고 다른 플레이어가 방 찾기를 요청을 한다면 방을 만들었던 클라이언트들의 아이피와 포트를 모조리 전달해버리는 형식입니다.

그렇게 된다면 두 번째 클라이언트는 서버와 통신하던 그 아이피 포트의 문을 열고 들어갈 수 있게 되죠 UDP는 단일 연결이라는 개념이 없으니까 말이에요.

TCP의 경우에는 이런 경우 내가 연결 중인 서버의 아이피와 포트가 아니기 때문에 바로 컷 해버릴 겁니다.

사실 공유기도 TCP라는 걸 이미 알고 있어요.

그 정보를 알고 있기 때문에 공유 기선에서 컷해 버릴 겁니다.

우리는 이 중간 서버를 랑데뷰 서버라고 부릅니다.

그리고 이런 형태의 모습을 홀 펀칭기법이라고 부릅니다.

-> 일단 공유기 밖으로 나갈 때 동적 포트 포워딩이 되고 그래서 외부에 아이피와 포트를 저장하는 서버를 둬서 그 아이피 포트를 저장한 뒤 중간에서 다리 역할을 하는 거죠.

 

네 UDP를 예전에 어떻게 썼는지에 대한 내용이 너무 길었는데요.

다시 돌아가서 RUDP에 대해서 얘기를 좀 해보죠.

사실 RUDP를 쓰는 이유를 쓰는 이유는 MTU에 맞춰서 잘라주는 역할이 존재하지 않고 재전송의 기능이 없습니다.

그런 기능들과 동시에 네트워크 트래픽을 좀 줄일 수 있다고 한다면 완벽한 RUDP가 되겠죠.

물론 이건 L7에서 직접 구현해야 됩니다 ㅎㅎ...

 

사실 UDP는 패킷을 잃어버리는 것에 대한 보장도 안 해줄뿐더러 한 번의 전송 = 하나의 데이터 가 되기 때문에 TCP처럼 MSS에 맞는 커팅도 존재하지 않는 거죠.

LoopBack으로 데이터를 보낼 때도 유실이 일어난다는 것 알고 계신가요?

만약 처리 한계를 넘어서거나 버퍼가 꽉 차게 된다면 유실이 되는데요.

이럴 경우 TCP는 안전하게 window size를 0으로 만들어서 더 이상 데이터를 보내지 않게 만드는 반면...

UDP는 와아아아악 쏟아부어서 결국 다 사라지게 되는 거예요.

이런 점을 보면 UDP는 확실히 TCP에 비해 유실이 많이 일어날 수 밖에 없습니다.

그럼에도 불구하고 TCP를 안 쓰고 UDP로 넘어가는 이유가 뭘까 하면 TCP는 자체적으로 하는 일이 너무 많습니다...

그리고 너무 과하게 친절하다 못해 답답할 정도로 친절합니다.

네트워크의 혼잡이 조금이라도 발생하면 바로 발을 빼서 양보부터 하는 이런 성격을 가졌기 때문에 느립니다...

그리고 요즘 사람들은 워낙에 똑똑해서 TCP의 일부 기능 정도는 충분히 구현할 머리가 되었습니다.

 

사실 이 정도 이유가 거의 대부분이라고 생각합니다.

단. PC게임에 한정해서요

이 경우가 모바일 게임으로 넘어가게 된다면 좀 달라지는데요.

모바일에서는 TCP가 좀 애매한 부분이 있습니다.

이 연결이라는 부분인데요...

모바일은 말 그대로 움직이면서 하기 때문에 실시간으로 IP와 Port가 바뀌어 버립니다.

그럴 때마다 재연결이라는 과정을 거쳐야만 한다면... 당연히 중간중간 끊어지게 될 것입니다.

물론 큰 티는 안 나겠지만 길면 2초 이상의 지연이 생기게 될 겁니다.

문제삼지 않으면 문제가 안일어날 것 같긴합니다.

좀 답답하지 않을까요 KTX를 타고 간다면 분단위로 이런 일이 일어날 건데요..?

모바일에서는 UDP를 이용해서 L7에서 새로운 프로토콜을 정의합니다.

내 위치가 이동해서 다른 곳으로 간다고 해도 새로운 연결 필요 없이 그냥 이전의 L7에서의 연결을 가지고 정리를 하는 거죠 토큰을 정의하는 겁니다.

네 그래서 정리를 하자면

-> TCP에서 IP Port가 바뀌면 연결이 끊어지게 되는데 다시 연결하는데 시간이 소요가 됩니다.

하지만 UDP는 연결이라는 개념이 존재하지 않기 때문에 그냥 보내면 끝입니다.

UDP를 이용하면 연결이라는 개념이 없기 때문에 우리가 위에서 연결을 정의해줘야 된다는 것이죠.

그러므로 L4윗 계층에서 새로운 세션의 정보를 제공, 그 정보가 맞다면 바로 실행이 가능하도록 만들어 주는 겁니다.

그러므로 RUDP에 대한 요구가 있을 수밖에 없는 겁니다.

 

대신 RUDP는 이런 조건은 만족하면 좋을 것 같네요.

연결에 대한 새로운 정의가 필요할 것이고, 데이터의 순서를 보장하며, 재전송이 보장되는 것입니다.

이 정도만 돼도 RUDP로 부를 수 있지 않을까요?

물론 여기에 네트워크 트래픽까지 제어를 한다면... 완벽하겠죠

이런 경우에 TCP랑 뭐가 다르냐고 할 수 있는데...

TCP는 네트워크 트래픽을 제어하는 게 무조건적으로 양보입니다.

하지만 우리 게임은 그렇지 않죠.

다른 게임회사와 우리 게임회사가 경쟁을 벌일 때 상대회사가 TCP고 우리 회사가 RUDP라면 우리 회사의 패킷은 신경 안 쓰고 보내버리겠지만 상대 회사 패킷은 서서히 발을 빼게 되니까요.

 

네 오늘도 역시 똥을 싸다가 멈춘 것처럼 또 포스팅이 끝나게 되었습니다.

오늘도 와주셔서 정말 감사드리고 긴 글 읽어주셔서 감사드립니다.

그럼 다음엔 winsocket API 중 기본적인 것 몇 개를 들고 오도록 하겠습니다.

그럼 안녕히 계세요.

320x100