상세 컨텐츠

본문 제목

네트워크 프로그래밍 실전에서 알아보는 홀펀칭 방법. 홀펀칭 관련

프로그래밍 관련/네트워크, 통신

by AlrepondTech 2020. 9. 17. 06:06

본문

반응형

 

 

 

=================================

=================================

=================================

 

 

 

 

 

 

 

출처: http://elky.tistory.com/259

 

 

[UDP] 홀 펀칭 (Hole Punching)

 

홀 펀칭 (Hole Punching)

- 정확한 명칭은 STUN (Simple Traversal of User Datagram Protocol Through Network Address Translators)

 

공유기라는 녀석이 라우터의 특성도 함께 가지고 있어 Routing Table 을 작성하기 위해 P2P 통신을 목적으로,

사전에 상대방과 패킷을 주고받고 하여 각자의 공유기에 Routing Table 을 작성하는 것을 [홀 펀칭]이라고 한다.

 

Full Cone NAT

내부에 있는 호스트들의 모든 요청은, 모두 같은 외부 ip, port 로 맵핑된다.

더군다나 어떤 외부 호스트든 공인 IP가 맵핑된 패킷 보내기에 의해 내부 호스트로 패킷을 보낸다.

 

Restricted Cone

목적지의 주소에 따라 NAT에 맵핑되는 포트가 달라진다.

홀 펀칭을 위해서는 목적지의 IP만 동일시하여 뚫어주면 목적지의 패킷을 받을 수 있다.

 

Port Restricted Cone

목적지의 주소에 따라 NAT에 맵핑되는 포트가 달라진다.

홀 펀칭을 위해서는 목적지의 IP와 포트를 동일시하여 뚫어주어야만 목적지의 패킷을 받을 수 있다.

 

Symmetric Cone

목적지의 주소와 포트에 따라 NAT에 맵핑되는 포트가 달라진다.

 

P2P로의 1:1 연결에서는 적어도 한 쪽이 Symmetric Cone NAT 가 아니거나 공인 아이피를 소유하고 있는 Peer 여야 한다.

 


홀펀칭 방식은 아래와 같다.

 

1. Full cone

-> PC에서 UDP 데이터를 공유기 밖으로 보낼 때 해당 PC의 IP와 포트 정보를 공유기가 기억하고 공유기의 포트와 맵핑을 해줌.

공유기의 해당 포트로 데이터가 오면 출발지 IP와 포트 정보를 상관하지 않고 해당 PC에 포워딩을 해줌.

 

2. Restricted Cone

-> PC에서 UDP 데이터를 공유기 밖으로 보낼 때 해당 PC의 IP와 포트 정보, 목적지 IP를 기억하고 공유기의 포트와 맵핑을 해줌.

공유기의 해당 포트로 데이터가 오면 출발지 IP정보를 비교하여 공유기에 기록된 목적지 IP와 같으면 해당 PC에 포워딩을 해줌.

 

3. Port Restricted Cone

-> PC에서 UDP 데이터를 공유기 밖으로 보낼 때 해당 PC의 IP와 포트 정보, 목적지 IP, Port 를 기억하고 공유기의 포트와 맵핑을 해줌.

공유기의 해당 포트로 데이터가 오면 출발지 IP 정보를 비교하여 공유기에 기록된 목적지 IP, Port 가 같으면 해당 PC에 포워딩을 해줌.

 

4. Symmetric NAT

-> PC에서 UDP 데이터를 공유기 밖으로 보낼 때 해당 PC의 IP와 포트 정보, 목적지 IP, Port 를 기억하고 공유기의 포트와 맵핑을 해줌.

만약 목적지 IP나 Port 번호가 바뀌면 새로운 포트로 맵핑해줌.

공유기의 해당 포트로 데이터가 오면 출발지 IP 정보를 비교하여 공유기에 기록된 목적지 IP, Port 가 같으면 해당 PC에 포워딩을 해줌.


구현 방법 

UDP 서버 (랑데뷰 피어)로 클라이언트가 UDP 패킷을 전송.

서버에 클라이언트의 IP와 Port 정보가 남는다.

이 정보를 바탕으로 현재 서버에 연결된 소켓에 접속할 IP와 포트 정보만 상대방 IP와 포트 정보를 넣고 상호간에 데이터 전송 시도하면,

Cone 방식은 UDP 홀펀칭이 성공한다.

 

간혹 Symmetric NAT 방식의 공유기가 있는데,

이 공유기 같은 경우에는 같은 소켓을 써도 UDP 데이터를 외부로 쏠 때, 목적지 IP나 포트 정보가 변경되면 공유기에서는 새로운 포트를 할당해 준다.

고로 나가는 것은 되나 들어오는 것이 안 됨.

한 쪽이 Symmetric NAT 방식이라면 상관 없는데 양쪽이 Symmetric NAT 방식이라면 낭패다.

UDP 릴레이 서버를 거치던지 다른 방법을 써야한다.

 

한쪽이 Symmetric NAT 방식이라면 반대쪽에서는 Symmetric NAT 쪽의 데이터를 받을 수 있다.

이 데이터를 받을 때 IP 와 포트 번호를 알아낼 수 있다.

알아낸 IP 와 포트 번호로 데이터 전송하면 됨.

 

 

 

=================================

=================================

=================================

 

 

 

출처: http://www.gamedevforever.com/47

 

실전에서 알아보는 홀펀칭 방법.

 


안녕하세요. 처음 이렇게 글을 올리게 됩니다.
저는 네오플에 다니고 있는 프로그래머 denoil 입니다.
다들 실력이 쟁쟁하신 분들이라서 제가 이런 글을 올려도 되나 하는 망설여지는데 개발자들끼리 공유하는 것은 좋다고 생각하여 이렇게 글을 올려봅니다.^^

 제가 오늘 발표할 내용은 홀펀칭 입니다. 현재 P2P 게임을 만드시는 분들께서는 모두들 아는 내용이시겠지만 처음 P2P를 접하거나 만드시게 되는 분들께는 도움이 되지 않을까 하여 이렇게 남겨 봅니다. 제가 지금부터 하는 말들은 실전에서 사용 했던 방법을 근거로 이야기 하는 것이지 네트워크 이론을 막 신경써서 하는것이 아님을 미리 말씀드립니다.

 일단 P2P를 사용하는 가장 큰 이유는 역시 빠른 속도 겠지요. 패킷이 서버를 거치지 않고 Peer에게 바로 전송이 되니 그만큼 빠른 것도 없겠지요. 
방법에는 TCP를 사용할 수도 있고 UDP를 사용할 수도 있겠습니다. TCP를 사용한다고 P2P가 아닌건 아니지 않습니까? Peer to Peer이기 때문에 서로 직접 연결만 되어 있으면 되는 것 입니다. 
허나! TCP를 사용하지 않는 이유는 UDP가 TCP보다 빠르기 때문 입니다. TCP는 패킷을 보장하기 위해 헤더가 더 붙고 뭐 순서를 보장하기 위해 block 하기도 하고 이것 저것 한다고 합니다.(자세한 내용은 책을 참고 하세요) 
UDP는 패킷을 보장하진 않지만 빠르다는 장점이 있습니다. 패킷 손실률이 있어 이부분은 직접 프로그래머가 제어를 해줘야 하는 단점이 있지만 어찌됐든 일반적으로 UDP는 TCP보다 빠르다고 합니다. (중국에서는 UDP보다 TCP가 더 빠르다는 이야기가 있습니다.) 
그래서 최신 P2P게임에서는 UDP를 많이 사용 합니다.

 Peer들 간의 통신을 하기 위해선 서로의 IP, PORT에 패킷을 전송하면 그만 입니다. 그러나 우리는 하나의 고정 IP를 가지고 공유기나 방화벽의 NAT( Network Adresss Translation )라는 장애물을 만나게 됩니다. NAT를 거치게 되면 사설 IP( 192.168.0.2 이런식의 IP )가 지급? 되게 됩니다.

 


 실제 공인IP 가 아니지요. 사설망에서만 서로간의 통신이 가능한 가상 IP라고 생각 하시면 됩니다. 그래서 NAT단에서 방화벽으로 IP, PORT등이나 인터넷을 막아버리면 아예 인터넷이 불가능 한 그런 상황도 만들어낼 수도 있고 인터넷 연결 없이 사설망에서만 돌아가게 인트라넷을 만들기도 합니다. 사설 IP로 서로 통신을 하게 되면 같은 NAT안에서의 통신은 가능 하지만 서로 다른 NAT에서는 당연히 통신이 되지 않습니다. NAT안에서만 존재하는 가상 IP이기 때문 입니다.
NAT의 종류에도 여러가지가 있습니다. 
1. Full Cone NAT
2. Restricted Cone NAT
3. Port Restricted Cone NAT
4. Symmetric NAT
이런것들이 있다고 합니다. 어떤 NAT는 먼저 패킷을 쏴서 포트를 뚫어놔야 하고 어떤 NAT는 먼저 패킷이 와야 포트가 뚤리고 뭐 어떤 NAT는 어쩌구 저쩌구해서 저쩌구 하고 제가 오늘 여기서 설명 드릴 것은 저런 NAT 타입에 대해서는 전혀 모르셔도 됩니다. 왜냐하면 저도 모르니깐요. :D 
모로 가도 서울만 가면 된다고 합니다. 이제부터 실전에서 배워보는 홀펀칭에 대해 알아보기로 하겠습니다. 이전 회사에서나 현재 회사에서나 모두 보니 홀펀칭의 방법은 동일 했습니다.

 지금까지 설명드리지 않은 홀펀칭! A4 용지 파일을 정리할때 구멍을 뚫는 펀칭도구를 홀펀칭이라고 부르지요? 말그대로 NAT로 인해 막혀있는 홀( 포트? )를 네트워크 패킷이 지나갈 수 있게 뚫는 것입니다. 
방법에는 여러가지가 있습니다. 위에 설명드린 것처럼 누가 먼저 보내고 받고도 있고 포트 번호의 구간을 정해 놓은 후에 하나씩 시도 해보는 방법( 예전 기억엔 그렇습니다. -_- )도 있습니다. 
하지만 여기서 포트번호는 한개로 고정 하겠습니다. 포트번호는 임의로 정하되 방화벽으로 막혀 있지 않는 포트 번호를 선택 합니다. 
현재 저희 게임에서 사용하고 있는 방법이고 문제 없이 잘 사용 하고 있는 방법 입니다. 
그리고 포트 번호 비교를 통해서 현재 어떤 NAT환경인지 체크할 수 있는 내용도 있지만 현재 주제가 길어 질 수 있으므로 생략 합니다. 

간단하게 3단계로 정리 해 보겠습니다.

1. 사설(private) IP로 패킷을 전송해 본다.
2. 안되면 공인(public) IP로 패킷을 전송해 본다.
3. 그래도 안되면 어쩔수 없이 Relay Server로 패킷을 전송해 대신좀 전송해 달라고 한다.

( 여기서 릴레이 서버는 패킷을 중계 해주는 서버입니다. 클라이언트로 부터 받은 패킷을 다른 클라이언트에서 전송만 해주는 역할을 담당하고 다른 일은 하지 않습니다. 지금까지 만난 프로젝트에서는 TCP를 사용했는데 전 회사의 다른 팀 게임에서는 UDP를 사용해서도 했다고 합니다. )

위의 세가지 입니다. 현재 나와있는 넷텐션의 ProudNet 같은 경우 다양한 테스트와 다양한 방법을 사용하여 홀펀칭을 하여 99%의 성공률 보인다고 합니다. ( 끼로님한테 들은 이야기 입니다. -_-)a 문제가 된다면 내용을 삭제 하겠습니다. ) 하지만 여기서 다루는 내용은 홀펀칭을 이용해서 99%의 성공율을 해주지는 못할 것입니다. 릴레이서버의 도움으로 99%까지는 가능 합니다. 기본적인 내용이고 현재 상용게임에서 사용하는 내용임을 거듭 강조 드립니다.

다시 돌아와서 천천히 방식을 전개해 보겠습니다. 위의 3단계를 시행하기 위해선 패킷을 보내려는 상대방의 사설, 공인 릴레이서버의 IP를 알아야 합니다. 그러려면 누군가는 나에게 상대방의 IP 정보를 알려 주어야 겠지요. 그것은 게임 서버가 역할을 하게 됩니다. ( 다른 서버가 해도 되는데 일단 게임 서버라고 하겠습니다. ) 게임 서버에게 나의 IP 정보를 통보하여 서버에서는 정보를 저장하고 있다가 해당 정보를 다른 유저에게 알리는 방식이 되겠습니다.

 이제 서버에게 통보를 할 정보를 수집해 보도록 하겠습니다. 처음 해야 할일은 자신의 IP를 알아내야 합니다. gethostname 함수를 이용하게 되면 자신의 IP를 알 수 있게 됩니다. 그러나 NAT환경에 있게 된다면 현재 나의 IP가 사설 IP 인지 공인 IP 인지 알 수 없게 됩니다. 그러면 공인 IP를 어떻게 알 수 있을까요? NAT환경 밖에 있는 서버는 알 수 있습니다. NAT환경 밖에 있게 되는 서버는 패킷을 받을때 어떤 IP로 왔는지 알 수 있기 때문입니다. 서버와의 통신을 한번 해야 합니다. UDP로 하도록 하지요. TCP로 하면 바인딩하고 커넥션하고 귀찮고 UDP로 간단하게 쏘고 받기만 하면 되는 일이니까요.

자 그러면 공인 IP를 알기 위해서 1바이트짜리의 빈 패킷을 서버로 보냅니다. ( 예를 들어서 빈 패킷일 뿐 제작하시는 분 마음대로 패킷에 내용을 채우셔도 상관 없습니다. ) 
그리고 서버는 패킷을 받았다면 받은 IP, PORT를 패킷내용에 실어서 패킷을 보내온 클라이언트에게 다시 전송을 해 줍니다. ( 이 과정에서 아마 일단 PORT가 열리는 것으로 알고 있습니다. 자세한 내용은..NAT 관련 문서를 찾아보아야 할 것 같습니다. )

 

만약 클라이언트가 일정 시간동안 서버로 부터 패킷을 받지 못했다면 다시 시도를 합니다. UDP는 패킷을 보장해주지 않기 때문에 손실이 되었을 수도 있기 때문입니다. 
클라이언트는 패킷을 받게 되면 정보수집은 끝 입니다. 
사설IP, 공인IP 모두 알게 되었습니다. 릴레이서버IP는 처음 로그인할때 게임서버에서 받기로 하지요. 
이제 수집한 정보를 게임서버에 로그인 한 후에 서버에게 보내주면 준비 끝 입니다.

위의 과정과 앞으로의 과정을 한눈으로 알아볼 수 있게 그림으로 표현 합니다.

 



내정보 보냈으니 서버에서는 데이터를 가지고 있겠고 각각의 Peer들은 상대방의 IP 정보를 알 수 있게 되었습니다. 사설 IP, 공인 IP, 릴레이서버 IP 모두 알 수 있게 되었습니다. 
이제 파티가 이뤄지기 시작하면 위의 정보를 가지고 처음 위에서 설명 했던 3가지를 시도 합니다.

 

 

일정 시간 동안 일정한 간격으로 Peer A는  Peer B에게 더미 패킷을 사설 IP로 전송 해 봅니다. 만약 Peer B가 해당 패킷을 받게 되면 상대방에게 받았다고 알려 줍니다. Peer A는  패킷을 받았다면 앞으로 사설 IP로 패킷을 보내면 됩니다. 
그러나 일정 시간 동안 받지 못했다면 이번에는 공인 IP로 패킷을 보내 봅니다. 공인 IP로 쐈을때 다시 패킷을 돌려 받았다면 앞으로 공인 IP로 쏘면 됩니다.
일정 시간 동안 또 받지 못했다면 서로 NAT환경에서는 통신이 불가능 합니다. 결국엔 릴레이 서버를 이용해야 하는 상황이 발생하게 됩니다. ( 최대한 릴레이 서버와의 연결은 안붙는게 좋습니다. 한단계를 더 거치기 때문에 느려지기 때문이죠. 그리고 여러명이 붙게 되면 그만큼 릴레이서버에 부담을 주기 때문입니다. )

처음부터 간단하게 다시 정리 해 드리겠습니다.

1. 클라이언트는 gethostname으로 사설 or 공인 IP의 주소를 저장함.
2. NAT환경이 아닌 게임서버 혹은 스턴서버에게 dummy Packet을 보냄. 
3. 서버는 받은 패킷의 IP, PORT로 IP, PORT를 패킷 내용에 담아 클라이언트에게 보냄.
4. 클라이언트는 사설 IP, 공인 IP 모두 저장.
5. 클라이언트는 수집된 사설 IP, 공인 IP를 서버에게 보냄.
6. 파티가 이루어질 경우 서버는 각각의 Peer에게 상대방의 사설,공인 IP를 전송.
7. 각각의 Peer들은 일정시간동안 사설 IP로 패킷 전송.
8. 사설 IP로 패킷 전송 실패시 공인 IP로 패킷 전송.
9. 공인 IP로 패킷 전송 실패시 최후의 보루 릴레이서버에게 맡김.

참 쉽죠잉?

여기서 주의 할점은 서로 패킷통신이 가능해지더라도 일정 시간동안 패킷을 주고 받지 않으면 포트가 막힐 수 있다고 합니다. 그러니 일정 시간동안 패킷이 오가지 않았다면 더미 패킷 혹은 핑 패킷이라도 쏴주면서 포트를 유지 시켜주면 좋겠습니다.

현재 상용게임에서 쓰고 있는 방식입니다. 얼마전 해외 서비스 통계상으로 봤을때 80%이상의 P2P성공율을 보였고 나머지 안되는 NAT 환경은 릴레이 서버를 함께 사용할 경우 98~99%의 P2P성공율을 보이고 있습니다.

많은 P2P 게임을 만드신 분들은 모두들 아는 내용일 것이라고 생각합니다. 각각의 회사마다 방식은 모두 조금씩 다르겠지만 일반적으로 저 방식을 통해서 홀펀칭을 하는 것으로 알고 있습니다. 저는 전문적으로 네트워크를 공부한 입장이 아닌 클라이언트 프로그래머 입니다. 잘못된 내용이 있다면 따끔히 지적해주세요. 저도 소스만 보고 익히고 공부한 내용이라서 틀린 부분도 분명 있을 것입니다. ^^
아무쪼록 여러분들께 좋은 자료가 되었으면 하며 이만 물러 나겠습니다. 
긴글 읽어주셔서 감사합니다.

-denoil-

 

-------------------------------------------------------------------------------------------------------------------------------------------------------------

 

  1. 덕분에 홀펀칭에 대해서 아주 쉽게 이해할 수 있었습니다. 감사합니다^^
    •  denoil 2012.01.09 18:58    
    • 너무 그림보단 글이 많아서 집중이 안되셨을텐데 감사합니다. ^^
  2.  몽상가 2012.01.09 17:00      
    •  denoil 2012.01.09 18:57    
    • 저도 심화내용까지는 보지 못해서 ^^; 다음에 시간내서 봐야 겠습니다. 감사합니다.
  3. http://en.wikipedia.org/wiki/UDP_hole_punching
    http://en.wikipedia.org/wiki/TCP_hole_punching

    좀더 심화내용은 역시 오픈 소스 네트워크 스택을 까보는 일이겠죠.. ^^

    좋은 내용 감사합니다.
  4. 크로스 2012.01.09 18:40      
    •  denoil 2012.01.09 18:57    
    • 감사합니다. ^^ 출처만 잘 밝혀주신다면 퍼가셔도 상관 없습니다.
  5. 홀펀칭에 대한 좋은 글 감사드립니다.
    저도 궁금해서 막 인터넷을 뒤져가며 찾아본적이 있었는데
    깔끔하게 잘 정리된 글인것 같아요!
    본문 포함 제 블로그에 퍼가고 싶은데 가능할런지요..?
  6. 크로스 2012.01.09 19:02      
  7. http://bluekms21.blog.me/10128882189
    감사합니다. 이렇게 퍼갔습니다. 내용은 전혀 손대지 않았고 앞으로도 좋은 글 부탁드립니다. ^_^
  8. Hybrid 2012.01.09 19:42      
    •  denoil 2012.01.10 15:45    
    • ㄷㄷ 이걸 보실줄이야 ㅋ
  9. 우아~ 홀펀칭 궁금했는데... +_+
    (선리플 후감상)
  10. Rhea君 2012.01.09 22:28      
    •  김포프 2012.01.10 06:15    
    • 그냥 내용 복사해서 붙이고... 미소녀 사진만 몇개 더 붙이시면 될듯?......
    •  친절한티스 2012.01.10 09:58    
    • 레아님 버전으로도 해줘욤
    • 김용준 2012.01.10 10:14    
    • 미소녀 사진 도입이 시급합니다.
    •  denoil 2012.01.10 15:45    
    • 오오 제가 쓰시려던 포스트를 낼름 한건 아닌지 쉽네요 ㅠㅠ
      중간에 네트워크 올리시길래 겹치지 않나 했는데 역시 겹쳤군요 죄송합니다 ㅠ
  11. 다음회에 홀펀칭 이야기를 할려고 헀는데 덕분에 포스트가 팍 줄었습니다!!!
    감사합니다. ^^
  12. sgpro 2012.01.10 10:28      
    •  denoil 2012.01.10 15:41    
    • 읽어주셔서 제가 감사합니다 ^^
  13. 고맙습니다. ^^
  14. Junios 2012.01.10 12:29      
    •  denoil 2012.01.10 15:42    
    • 감사합니다 ^^
  15. 잘 보고 갑니다.
  16.  Silverchime 2012.01.10 14:44      
    •  denoil 2012.01.10 15:44    
    • 감사합니다^^
      저도 프레넬 이펙트 잘봤습니다 ^^
      굉장히 디테일하게 써 있어서 깜짝놀랐습니다!
  17. 이런게 있군요! 감사합니다
  18. ∞ 기시감 2012.01.10 16:10      

    한 5-6년전쯤? 네트워킹에 대한 테스트 방책이 별로 없었을때
    공유기 사용하는 유저들이 P2P 방식 사용하는 게임을 하면 안되는 경우가 있어 많이 데었었죠.

    PC방은 보통 IP를 모두 구입해 사용하는데 가정에 공유기 보급이 한참 오르던 시절이라 네트워크에 대한 테스트도 시작했었습니다.

    공유기 메이커에 따라서도 이게 잘되는 놈이 있고 안되는 놈이 있고 그러더라구요 ㅎㅎ
  19. 요걸 홀펀칭이라고 하는군요 
  20. kpro 2012.01.10 18:34      
  21. 홀펀칭 내용중에 제일 많이 찾아보게되겠군요. 감사합니다~
  22. 울레리오 2012.01.12 15:19      
    • 울레리오 2012.01.13 15:18    
    • 위에보다보니 이런내용이있네요~
      (중국에서는 UDP보다 TCP가 더 빠르다는 이야기가 있습니다.)

      -> 제가 한달정도 중국가서 테스트해본결과 중국도 UDP가 잘됩니다. 홀펀칭율도 약 85% 이상 나옵니다.(다른 동남아 지역과 비슷) 허나 중국인들 인터넷 사용자가 워낙 많아 인터넷사용자가 늘어나는 저녁시간대가 되면 회선망이 과부화되는거 같습니다. TCP도 툭툭끊어집니다. 결론은 트래픽을 줄이는게 관건이라 생각됩니다. 참고하시길 ^^
    • 울레리오 2012.01.13 15:22    
    • 제 생각에 중국에서 UDP사용을 잘 안하려는 이유는
      보안문제와 천차만별인 중국 인터넷 환경(NAT장비등)을 서버가 부담하는게 좋다고 생각해서 인듯합니다.
      FPS 서비스도 TCP로 하는 게임도 있더군요.
      근데 중국의 인터넷환경이 점점 좋아지는 추세이므로 점점 UDP사용하는 게임들이 늘어나지 않을까 생각됩니다.
    •  denoil 2012.01.13 17:24    
    • 저희 게임도 UDP Module이 시작할때 릴레이서버에 Connection을 먼저 한 후에 한꺼번에 private, public, Realy를 시도하는 루틴이 있습니다. ( 먼저 오는 패킷으로 선택됩니다. )
      그런데 개인적으로 relay Connection수를 줄이고 릴레이서버 부하를 줄이기 위해 위의 방식을 예시로 들었습니다.( private -> public -> realy 시도 순서 )
      홀펀칭 속도를 생각하면 울레리오님이 말씀하신대로 선릴레이 후 홀펀칭을 통해 direct udp를 하는게 맞는 것 같습니다. ^^ 
    •  denoil 2012.01.13 17:26    
    • 좋은정보 감사합니다. ^^
      중국이 TCP가 더 빠르다는 이야기가 있던것에 대해서는gpgstudy에서 지나가면서 들은 이야기 같습니다. 아마 울레리오님께서 말씀하신것처럼 중국 인터넷환경을 서버가 부담하는게 좋다고 하신 내용 그 내용이었던것으로 기억하는데 잘 기억은 안나네요.
      ( 끼로 말로는 소닉 다니셨다는데 저도 소닉 출신이예요 반갑습니다. ^^ )
    •  끼로 2012.01.13 22:00    
    • 영운이형이랑 진영이형이 같은 기간에 소닉에 있었는줄 알았는데 아니었네요.. 서로 아는 사이인줄 알았..
  23. 안녕하세요 넷텐션 울레리오입니다. 잘보았습니다. 보다보니 저희 프라우드넷 이야기도 나오네요~
    간략하게 저희엔진에 대해 말씀드리면, 저희 엔진은 선 릴레이 후 홀펀칭을 사용하여 reliable한 패킷을 보낼경우 100% 전송을보장합니다. p2p를 하실때 먼저 릴레이 통신이 되게한후 뒷단에서 direct udp가 되도록하면 손실나는 경우를 줄일수 있을거라 생각되네요.
  24. 초보자 2012.02.23 22:54      
    • 초보자 2012.02.24 13:15    
    • 이런 실수를 gethostname를 gethostbyname으로 봤네요. 어떻게 이런 실수를...부끄럽네요. ㅎㅎ 어쨌든 글에 있는 함수를 테스트 했더니 잘 돼요. 감사합니다.
  25. 좋은 글 잘 봤습니다. 질문이 좀 초라하긴 하지만 궁금한 점이 있어서요. 우선 전 프로는 아니고 늦깍이학생입니다ㅎㅎ 
    질문은 저기 함수 중에 gethostbyname은 도메인이 있어야 사용할 수 있지 않나요?
    winsock으로 사용할 때는 도메인을 ip주소로 바꾸는 용도로만 사용했었는데, 이 글을 보고
    아무리 찾아도 도메인 넣으라는 글 밖에 없는데, 제가 모르는 사용방법이 있나 해서요. 나중에 시간이 나신다면 조그마한 힌트라도 알려주시면 좋겠어요. 감사합니다.
  26.  zelon 2012.03.20 01:19      
    . 성공률이 100% 인지는 사실 '보장' 을 못해서;; 여튼 99% 까지는 잘 되었던 것 같네요.

    실전에서는 역시 4가지의 NAT 종류보다는, 사설ip, 공인ip, 릴레이서버 정말 이렇게 되는것 같습니다.

    개인적인 의견으로 ^^ 언급하시면 좀 더 좋았을 것 같은게, 같은 NAT 안에서는 공인ip 에 패킷을 보내면 안 간다 정도가 될것 같아요(왜 저렇게 되었는지 과정도 알아두면 좋으니까요~). 공인 ip 라서 아무나 보낼 수 있을 것 같은데 실제로는 내부(!)에서는 공인ip 를 모르더라구요. 즉, "같은 집(같은 공유기 아래)에 있는 컴퓨터들끼리는 사설ip 로만 통신이 된다. 그래서 공인ip 로도 보내보고, (같은 집에 있을 수 있으니) 사설ip 로도 보내본다" 정도를 알고 쓰면 좋을거 같아요~

    실전에서 잠시 쉰지 좀 되어서, 혹시 잘못된거 있으면 알려주세요~
  27. 역시 p2p 상용게임은 비슷한 역할을 해왔었네요. 최후의 수단은 릴레이 서버죠. 저도, 선 p2p 후 릴레이 서버를 썼었었습니다(서버 부하도 괜히 찜찜하고해서;
  28. 나그네 2012.04.04 22:34      
  29. 포스팅 잘보았습니다..

    세번째방식.. 릴레이서버를 통한 방식은.. 홀펀칭 및 p2p는 아닌것으로 보입니다..
    홀펀칭이 실패했을 때의 대비책 정도???
    그리고 이 방식은 A,B 피어 모두 릴레이 서버에 접속되어 있어야 사용가능합니다.
    B가 릴레이 서버에 접속하지 않은 상태에서는 릴레이 서버 또한 A와 마찬가지로 B에게 패킷을 보낼 수가 없는 것입니다.

    그리고, gethostname으로 얻어지는 ip는.. NIC카드가 여러개 있을 때 실제 연결에 사용된 NIC를 선택하기 쉽지않습니다.
    연결 후에 연결된 소켓에 대해 accept 함수 호출시 받아오는 sockaddr 구조체에 담긴 아이피를 사용하거나, getpeername/getsockname 함수를 통해 sockaddr 구조체를 얻어와 아이피를 확인하여야 할 것입니다.
  30. ffe 2012.06.09 12:09      
    •  denoil 2012.06.10 23:29    
    • 상대방과 서로 다른 NAT에 있더라도 중간에 설명드렸다 시피 중간에 NAT환경이 아닌 서버를 통해서 각각 서로의 클라이언트의 public ip와 port를 얻어오는 부분이 있습니다. 그래서 서로 다른 NAT환경에 있더라도 얻어온 공인 ip,port를 이용해서 보내게 되면 매핑이 되는 것으로 아는데 그걸로도 통신이 안되면 제일 마지막에 설명드렸던 중계 해주는 서버를 통해서 서로 통신을 하는 방법 밖에 없겠지요. 답이 되었는지 모르겠습니다. ^^;;
  31. 제가 잘 몰라서 이해가 안가는점이 있습니다.
    상대방과 서로 다른 NAT환경에 있더라도 
    공인 ip로 보내면 통신이 된다는건가요??
    NAT에서 해당 device로 찾아가는 과정이 없어도 자동으로 찾아서 들어가는건가요?? 궁금합니다
  32. sownership 2012.06.09 15:59      
  33. 쉬운 설명 너무 감사 드립니다 ^^
    큰 도움이 되었습니다.
  34. 죽기살기 2012.06.11 13:13      
    •  denoil 2012.06.12 11:15    
    • 아 저 내용에서 릴레이서버의 내용은 완전히 배제 하고 쓴글이라서 자세히 설명하지 않았습니다. 제가 질문의 요지를 잘 파악한것인지 모르겠는데 일단 릴레이서버는 중계 해주는 역할이기 때문에 NAT환경이 아닙니다. 그리고 각각 클라이언트의 public ip, port를 수집하기 위해 게임서버가 중간에서 해준다고 했는데 이 정보를 이용해서 릴레이서버에게 "난 이 ip,port에게 보내고 싶어 네가 대신좀 해줄래?"하고 패킷을 보내면 릴레이서버에서는 패킷을 받으면 패킷 정보를 까서 "이놈한테 보내면 되겠고만" 하고 해당 클라이언트에서 패킷을 던지는 식입니다. 그래서 릴레이 서버를 거치게 되는경우엔 사설 ip,port가 필요없게 됩니다. 그리고 릴레이서버가 어떤 프로젝트에서는 UDP, 어떤 프로젝트에서는 TCP를 사용 한다고 하는데요. TCP로 연결이 맺어진 상태라면 릴레이서버는 패킷을 받아서 연결되어 있는 다른 클라이언트에게 그냥 토스만 하면 됩니다. UDP쪽 홀펀칭은 저 위에 "끼로"님께서 오래전에 했던 부분이라 그분은 여쭤보면 될듯싶습니다.^^
  35. 안녕하세요. 네트워크를 전혀 모르는 바보 개발자 질문 하나만 할게요~;;
    갑자기 네트워크 관련 프로젝트를 하게 되어 아는게 없어 자료를 찾던중 글쓴이 님의 좋은 포스트를 읽고 궁금한 점이 생겼네요.

    세번째 방식에서 릴레이 서버를 통해 중계를 해야 한다고 말씀하셨는데,
    혹시 클라이언트가 중계서버에게 공인ip(AP의 IP)와 사설IP(AP로부터 얻은 Private IP)를 저장해두어야 하나요? 글을 읽어봐서는 공인IP만 저장을 한다는것 같은데 그렇타면 AP에서는 무엇을보고 사설 IP로 포워딩을 해주는지 이해가 잘 되지 않아서요..ㅠ_ㅠ
    멍청한 질문일지 모르지만 알려주시면 감사하겠습니다~^^;
  36. 죽기살기 2012.06.15 19:32      
    • 릴리 2012.06.18 14:49    
    • NAT이 뭘까요, 글 초반부에도 있듯이 다른 사설IP를 부여해주는 장치입니다. IP가 다른데 무슨 구별이 필요할까요?
  37. 안녕하세요. 위에 답변감사합니다~!!
    "끼로"님이 어떠한 분이지 몰라 다시 여기에 질문 하나만 더 할게요..ㅠ_ㅠ

    제가 궁금한 것은 NAT A에 두개의 클라이언트가 물려 있다고 가정하면 어떠한 클라이언트에게 
    어떠한 data(infomation)를 보고 어떻게 해당 클라이언트를 찾아 들어가는지 궁금합니다.

    자세히 다시 설명드리면
    지금까지 제가 공부한 바로는..
    1. Client(A)는 서버에게 P2P 통신을 하려는 Client (B)의 Public Ip, Port / Private Ip, Port를 받는다.
    2. 서버로 부터 받아온 Public/Private 주소에 UDP 패킷을 보내고 
    if Private 주소에서 받으면 direct로 통신
    if Public 주소에서 받으면, 받은 NAT(B)에서는 받은 패킷의 정보가 없기 때문에 버려진다.
    3. Client (B)에서도 Client(A)로 UDP 패킷을 보낸다.
    4. NAT(A)에는 이미 NAT(B)로 패킷을 보냈던 정보가 저장이 되어 있기 때문에 Client (A)에게 데이터가 전달된다.

    라고 이해를 하고 있습니다. 하지만 이 상황에서 위에 말씀드렸다 싶이 NAT(A)에 두개 이상의 Client가 있다면,
    이 Client들 중에 패킷을 보냇던 Client를 어떻게 구별을 하는지 궁금합니다.
    혹시 시간이 되신다면 답변해주시면 감사하겠습니다.
    그럼 수고하세요..
  38. 항해자 2012.09.24 10:01      
  39. 정보 감사합니다.
    많은 도움이 되었습니다.
    덧글도 읽어보니.. 많은 도움이 되었네요. 
    감사합니다.
  40. 퐈니아 2013.07.03 17:18      
  41. 잘 보았습니다.
    덕분에 머리속에 밑그림이 그려지는것 같습니다.ㅎㅎ
  42. 지나가다 2013.10.22 16:03      
    •  denoil 2014.10.01 11:56    
    • 안녕하세요. 1년이 지난 지금 댓글을 답니다.
      사설 IP는 각각의 Peer들이 서버로 전송해 주고 서버는 accept된 ip,port(공인)와 Peer가 패킷에 전송해준 사설ip,port를 모아 둡니다.
      그리고 Peer들 끼리 연결이 필요할 때 상대방의 사설, 공인 ip, port를 서버에서 전송해 주게 되면 Peer들은 받은 ip, port로 패킷을 쏩니다.
      여기서 사설 IP로 전송은 한번 시도해 보는 것입니다. 같은 NAT환경안에 있는 사람에게는 공인ip,port로는 패킷전송이 안되기 때문에 같은 NAT환경안에 있는 사람이라고 가정하여 먼저 시도해보는 것입니다. 그리고 실패시 공인 ip,port로 전송 하는 것이지요. (순서는 상관없습니다.)
  43. 지나가다가 우연히 봤습니다.
    시간이 꽤 지나서, 댓글 안보실수 있겠지만, 만약 보신다면 답변 좀 부탁합니다.
    다른것은 다 이해가 되는데, "사설 ip로 전송"이라는 것을 이해하지 못하겠네요. 
    제가 사설 IP에 대해서 잘못 이해하고 있는 것 같지는 아닌데, "사설 IP로 전송"하는 것이 어떻게 가능하지요? 아니면 제가 모르는 어떤 내용을 생략하십겁니까?

 

 

반응형

 

 

728x90

 

 

=================================

=================================

=================================

 

 

출처: http://egloos.zum.com/sweeper/v/2431396

 

Hole Punching

 

이 문서는 http://www.brynosaurus.com/pub/net/p2pnat/ 에 있는 
챕터3. UDP Hole punching을 번역하면서 개인적인 첨언을 덧 붙인 형식으로 작성되었다.

이 후 두 개의 클라이언트는 A와 B로, 랑데뷰 서버는 S로 통칭된다.

------------------------------------------------------------------------------------------------------------

UDP 홀펀칭은 클라이언트가 NAT 밑에 있더라도, 
랑데뷰 서버를 통해 두 클라이언트간 P2P 다이렉트 세션 형성을 가능하게 해준다.


1. 랑데뷰 서버

홀펀칭은 클라이언트 A와 B가 이미 랑데뷰 서버 S와 active UDP 세션을 가지고 있다고 가정하고 시작한다.
클라이언트가 서버 S에 등록되면, 서버는 클라이언트의 2개의 endpoint를 기록한다.
(one : private ip/port, two : public ip/port)

클라이언트는 서버에게 자신의 private ip/port를 포함한 등록 패킷을 보내면, 
서버는 패킷에 포함된 private ip/port와 실제 UDP 통신상에서 알아낸 public ip/port 2개의 endpoint를 모두 획득하게 된다.
만약, 클라이언트가 NAT 밑에 있지 않은, 즉 공인 IP를 쓴다면 private ip/port는 public ip/port와 일치하게 된다.


2. P2P 세션 연결 시나리오

클라이언트 A가 B와 직접 UDP 세션을 열고 싶어한다고 가정해 보자. 홀펀칭은 다음과 같이 진행된다.

1. 최초 A는 B에게 어떻게 도달해야 하는지 모른다. 따라서 A는 S에게 B와 UDP 세션 연결을 요청한다.

2. S는 A에게 B의 private/public endpoints 정보를 전송해 준다. 이와 동시에, S는 B와 연결된 UDP 세션을 통해
A의 private/public endpoints 정보를 포함하는 접속 요청 패킷을 전송한다.

3. A가 B의 endpoints 정보를 S로부터 받으면 A는 private/public endpoints로 UDP 패킷을 전송하기 시작하며, 
두 개의 endpoints 중 어느 쪽으로든 올바른 응답이 B로부터 오기를 대기한다. 
이와 유사하게, B가 A의 private/public endpoints 정보를 받으면, B역시 A로 UDP 패킷을 전송하기 시작한다.


이제 세 가지의 네트워크 토폴로지에 대해 UDP 홀펀칭이 어떤 식으로 이루어지는 지 확인할 필요가 있다.

1. 두 클라이언트가 같은 NAT 밑에 있는, 하나의 private network에 소속되어 있는 경우.

2. 대부분의 경우인데, 두 클라이언트가 서로 다른 NAT 밑에 있는 경우.

3. 두 클라이언트가 2단계의 NAT 들 밑에 있는 경우 : 통상적으로 첫번째 NAT는 ISP의 그것이...
두번째는 각기 사용하는 home-networking을 위한 가정용 NAT 이다.

일반적으로 어플리케이션 스스로 물리 계층에서의 네크워크가 어떻게 구성되어 있는 알아내기란 쉽지가 않다.
STUN과 같은 프로토콜이 통신 통로상에서 NAT 구성에 대한 정보를 줄수도 있으나,
이 정보는 반드시 신뢰될 만한 것이 아니며, 특히 NAT가 다단계인 경우 더더욱 그러하다.

그럼에도 불구하고, NAT가 대체적으로 RFC를 충족하도록 구현되어 있다면,
어플리케이션 상에서 어떤 식으로 네크워크가 구성되어 있는지 몰라도 홀펀칭은 대개의 경우 잘 동작한다.


3. Peers behind a common NAT

 

두 클라이언트가 같은 NAT 밑에 있는 경우 위 그림과 같이 당연하게도 외부에서 보기에는 public ip가 똑같다.

A가 S로 UDP 세션을 연결하였고, NAT는 A-S 연결에 62000번 포트를 할당, 맵핑하였다.
B도 S랑 세션을 연결하였고, NAT는 B-S 연결에 62500번 포트를 할당, 맵핑하였다.

A가 S를 이용하여, B와의 UDP 세션을 연결하기 위해 홀펀칭을 시도한다고 가정해보자.

1. A는 S에게 B와의 연결 요청을 전송한다.

2. S는 A에게 B의 private/public endpoints 정보를, B에게 A의 private/public endpoints 정보를 전송한다.

3. 두 클라이언트 모두 private/public endpoints로 UDP 패킷을 서로에게 직접 전송하기 시작한다.

4. 두 클라이언트 간 public ip/port로의 UDP 패킷 통신은 
NAT가 hairpin translation을 지원하느냐 하지 않느냐에 따라 서로에게 도착할 수도 그렇지 않을 수도 있다.

5. 두 private endpoint 간 메시지는 서로 도착할 것이며, 두 클라이언트 간 다이렉트로 전송되는 것이
NAT를 거쳐가는(through public endpoint) 것보다 대부분 빠르므로, 어플리케이션은 private endpoint 통신을 선호한다.


결론 : 두 클라이언트의 public ip가 같다면, 이는 같은 NAT 밑에 있는 것을 의미하고,
같은 NAT 밑에 있다고 판단되는 클라이언트끼리의 홀펀칭은 private endpoint로 하면 된다.


4. Peers behind different NATs (most case)

 

그림과 같이 A와 B가 서로 다른 NAT 밑에 있는 경우에 대해 알아보자.

A와 B는 4321 포트에서 S의 1234 포트로 UDP 세션을 초기화시켰다.
이 outbound 과정을 핸들링하면서 NAT-A는 A-S 세션에 대해 155.99.25.11:62000 포트를 할당하였고,
NAT-B는 B-S 세션에 대해 138.76.29.7:31000 포트를 할당하였다.

1. A가 S에 등록하는 과정에서, A는 자신의 private endpoint가 10.0.0.1:4321(10.0.0.1은 NAT-A에서의 A의 ip)임을 알리고,
등록과정에서 S가 파악한 A의 public endpoint(155.99.25.11:62000, NAT-A가 할당한)와 함께 이를 A의 정보로 저장한다.

2. 역시 S에 등록하는 과정에서 자신의 private endpoint가 10.1.1.3:4321임을 알리면,
등록과정에서 S가 파악한 B의 public endpoint(138.76.29.7:31000)와 함께 B의 정보로 저장한다.

3. 이제 A는 위 그림의 "The hole Punching Process"를 따라 B와 직접적인 세션을 연결한다.

4. 우선, A는 S에게 B와 직접 연결을 요청한다. 이에 대한 응답으로 S는 A에게 B의 private/public endpoints에 대한 정보를,
B에게 A의 private/public endpoints에 대한 정보를 각각 전송해 준다.

5. A와 B는 서로의 two endpoints에 대해 직접적으로 UDP 패킷을 전송하기 시작한다.

6. A의 첫 메시지가 B의 public endpoint로 발송되었다고 가정해보자. 

이 메시지는 NAT-A를 통과하기 때문에, NAT-A는 이 패킷이 새로운 세션(A-B)에 대한 첫 UDP 패킷임을 인지한다.
새로운 세션의 source-endpoint(10.0.0.1:4321)가 A-S 연결의 source endpoint와 같지만, destination은 A-S의 그것과 다르다. 

여기에서 NAT type 별 양상이 달라지는 데 간단하게 정리하면 다음과 같다.

    7.1 Full cone : 한 번 내부(private endpoint)에서 패킷이 전송된 적이 있는 source(public) endpoint로는
                            외부에서도 자유롭게 패킷을 전송할 수 있다.

    7.2 Restricted cone : 한 번 내부에서 destination ip로 패킷이 전송된 적이 있는 source endpoint로는
                                      해당 destination ip로부터의 패킷을 전송 받을 수 있다.
    
    7.3 Port restricted cone : 한 번 내부에서 destination ip:port로 패킷이 전송된 적이 있는 source endpoint로는
                                             해당 destination ip:port로부터의 패킷을 전송 받을 수 있다.

    7.4 Symmetric cone : 내부에서 외부로 패킷이 나갈 때 destination이 달라질 때마다 NAT가 할당하는 포트가 바뀐다.
                                       예를 들어 1.1.1.1:1000에서 222.222.222.222:1234로 패킷이 나갈 때 NAT가 20000번을 할당한다면...
                                       1.1.1.1:1000에서 111.111.111.111:4321로 패킷이 나갈 땐 private endpoint가 같을 지언정,
                                       NAT는 다른 포트를 할당하여 결과적으로 public endpoint가 달라지게 된다.

8. A와 B 모두 full cone이 아니라고 가정해 보자. 

만약, B->A로의 첫 패킷이 NAT-B를 통과하지 전에, A의 패킷이 NAT-B에 먼저 도착하면,
NAT-B는 A의 incoming message에 대해 unsolicited message라고 판단하여 버려(drop) 버린다.

이 후 A->B도, B->A도 1번씩은 서로 cross하게 NATs를 통해 전달되고 난 이후에야,
A와 B는 직접적으로 열린 hole을 통해 UDP 통신이 정상적으로 이루어 진다.


5. Peers behind multiple levels of NATs

 

NAT-C는 소수의 ip 주소로 수많은 사용자들을 받아들이기 위한, ISP에 의해 설치된 거대한 산업용 NAT이라고 치고,
NAT-A와 NAT-B는 NAT-C로부터 할당받은 ip를 소규모 단위로, 홈 네트워크 구성 등의 이유로 쓰이는 NATs라고 치자.

이 상황에서 서버 S와 NAT-C만이 public ip를 가지고 있다.
즉, NAT-A와 NAT-B에서 쓰이는 "public" ip는 실제로 NAT-C 하에서 private 하며,  
이 private 한 NAT-A와 NAT-B 밑에 A와 B가 놓여있다.

이제 A와 B가 홀펀칭을 통해서 직접 P2P 연결 구성을 시도한다고 해보자. 
아마 최적의 라우팅 방식은 A가 NAT-B에 있는 B의 "semi-public" 주소, 10.0.1.2:55000으로 메세지를 보내고,
B 역시 NAT-A에 있는 A의 "semin-public" 주소, 10.0.1.2:45000 으로 보내는 방식일 것이다. 

하지만 불행히도, A와 B가 이 주소를 알 방법은 없다. 
왜냐하면 서버 S는 오직 클라이언트의 진정한 전역 public 주소만 보기 때문이다. 
또한 A와 B가 이 주소들을 어떻게든 알았다 하여도 이들이 사용 가능할지는 미지수이다. 
이는 ISP의 prviate 주소 세계의 IP주소 할당과 클라이언트의 private 세계에서의 IP 주소 할당이 충돌할 수 있기 때문이다. 

예를 들어서, NAT-C에서 NAT-A로 할당한 IP주소가 NAT-B에서 B로 할당한 주소인 10.1.1.3 일지도 모르는 것이다. 
이러면 B는 자기 자신에게 메세지를 보내는 결과가 나와버린다.

따라서, P2P 통신을 위해 클라이언트들은 S에게 보여지는 그들의 전역 public 주소를 이용하는 수 밖에는 없다. 
그리고 이는 NAT-C에서 제공하는 hairpin 혹은 loopback 변환에 의존해야한다. 

1. A가 B의 public endpoint(155.99.25.11:62005)으로 UDP 패킷을 보낼 때 
NAT-A는 먼저 패킷의 source endpoint를 10.0.0.1:4321 -> 10.0.1.1:45000으로 변환한다. 

2. 이 패킷은 NAT-C에 도착하고 이 패킷의 destination이 NAT-C의 변환된 public endpoints 중에 하나라는 것을 알아차린다. 

3. 만약 NAT-C가 잘 동작한다면, 패킷의 source endpoint와 destination을 모두 변환하고 이 패킷을 "돌려서" private 네트워크로 보낸다. 

4. 이제 패킷의 source endpoint는 155.99.25.11:62000이고 destination은 10.0.1.2:55000 이다.

5. B의 private 네트워크로 이 패킷이 들어가면서 NAT-B가 이 패킷의 도착 주소를 변환, B에 도착하게 된다.


위의 procedure는 NAT가 hairpin을 지원할 때 가능한 시나리오이다.
조사에 의하면 거의 대부분의 NAT가 hairpin을 지원하지 않는다고 한다. (특히 가정용은 절망적인...)
따라서 사실상 거의 대부분의 multiple level NAT하에 있는 peer-peer 통신은 불가능한 경우가 많다.


6. UDP Idle timeout

NAT 하에서 어플리케이션과 관계없이 UDP 통신은 타임 아웃이 있다. 
이 타임 아웃은 일정 기간 서로 통신이 없으면 hole을 닫아버리는 것을 의미한다.

불행하게도 이 타임 아웃에 대한 기준은 없으며, NAT 별로 다 다르다.
심지어 어떤 NAT는 3-4초 동안만 통신이 없어도 hole 이 닫혀버려 다시 홀펀칭을 해야할 수도 있다.

따라서, 서로 홀펀칭된 것을 유지하려면 열려 있는 세션들끼리의 최소한의 keep-alive는 보장이 되어야 한다.
UDP를 빈번한 패킷 전송에 사용하는 경우에라도 어느 정도 통신이 없는 경우를 대비한 하트비팅이 필요할 듯 하다.
예를 들어, 4초간 패킷 통신이 한 번도 없었다면... keepalive 패킷을 한 번 쏴주자 머 이런 식으로 말이다.

 

 

=================================

=================================

=================================

 

 

출처: https://kldp.org/node/140106

 

 

혹시 HolePunching 활용한 예제소스 있을까요?

 

안녕하세요 네트워크프로그래밍을 공부하고 있습니다..^^

P2P 기능 구현 관련하여 NAT 뒤에 연결된 클라이언트끼리 1:1 통신이 되도록 해야하는데요

그럴려면 Hole Punching 기능을 사용해야 하는걸로 알고 있습니다

클라이언트끼리 파일송수신이 되게 하기 위해선 UDP 보단 TCP 를 사용하는게 좋을거 같은데요..

혹시 TCP Hole Punching 기능관련된 예제소스 어디 없을까요..?

‹ link down인데 랜포트의 led는 들어오는 경우는 어떤 경우에 생길까요?리눅스(ubuntu)에서 rtsp서버 구현 어떻게 해야 하나요? ›

예제라기 보다.. 원리가 UDP와 동일합니다...

글쓴이: 익명 사용자 작성 일시: 화, 2013/09/24 - 1:13오후

예제라기 보다.. 원리가 UDP와 동일합니다... 그냥 TCP로 쏘시면 됩니다.

다만 UDP 홀펀칭은 되는데 TCP홀펀칭은 안되는 NAT 장비들이 존재합니다.

장비만 문제없다면 잘 될겁니다.

»

아 그렇군요.. ^^

글쓴이: dhyoon1 작성 일시: 화, 2013/09/24 - 1:28오후

답변 감사합니다

그럼 UDP 든.. TCP든 홀펀칭이 이용된 참고할만한 예제소스같은거 구할수 없을까요..?^^

»

검색해보면 아래와 같은 글들이 보이네요.. 자세히는

글쓴이: klenui 작성 일시: 화, 2013/09/24 - 2:42오후

검색해보면 아래와 같은 글들이 보이네요.. 자세히는 보지 않았습니다만..

http://ramonli.blogspot.kr/2012/03/tcp-hole-punching-how-to-establish-tc...

http://www.gamedevforever.com/47

한 5년전에 홀펀칭 고민했을 때, python으로 10줄이 안되는 코드 작성해서 테스트 했더니 동작했던 기억이 나네요..
네트워크 쪽은 원리에 비해 코드가 복잡하니까.. 먼저 동작원리를 파악하는게 도움이 되실겁니다.

»

감사합니다~~

글쓴이: dhyoon1 작성 일시: 화, 2013/09/24 - 2:43오후

감사합니다 참고하겠습니다~~^^

»

홀펀칭 없이도....

글쓴이: simminjo 작성 일시: 화, 2013/09/24 - 1:38오후

홀펀칭....STUN 이라고도 불리웁니다.
STUN 없어도 NAT 뒤의 클라이언트간에 통신은 가능합니다.

중계해주는 서버를 거치면 가능해지죠..REALY 방식이라고도 합니다.
STUN은 라이브러리들이 있었던것같긴한데.....

직접 구현해본다고 학생때 설쳐보다가 결국 실패하고 좌절했던 기억만 남아있네요.

---------------------------------------------------------------
Opensource에 기여하는 것이 꿈입니다.
내가 만든 코드를 모두가 사용할 때 까지~

»

릴레이서버도 사용하는데요..^^

글쓴이: dhyoon1 작성 일시: 화, 2013/09/24 - 2:44오후

릴레이서버는 클라이언트 간의 파일송수신엔 직접적으로 관여하지 않아야 해서요..ㅎㅎ

릴레이서버는 단지 클라이언트끼리 public IP와 Private IP 정보만 중계하는 역할을 해야하거든요.. 안그럼 P2P연결이라고 볼수가 없어서..
조언감사합니다^^

»

ㅎㅎ

글쓴이: simminjo 작성 일시: 화, 2013/09/24 - 3:36오후

보시다 보시면 아시겠지만 공유기 방식마다 홀펀칭 방식이 다릅니다.

half cone , full cone, 또 다른방식 등등 각각의 방식에 따라 펀칭 기법이 달랐던것으로 기억합니다.
해당 문제로 인해 iptime측에 정보를 요청했으나 공개해주진 않더군요.

홀펀칭이 결국은 되지않는 상황도 발생할수 있습니다.
nat 밑의 nat밑의 nat 뭐 이런 이상한 경우가 나올수 있는데 어떤 케이스에선 결국 안뚫리는경우가 있더군요.
그런경우는 결국 relay방식을 쓸수밖에없다고 본듯합니다.

하도 오래전에 해당 부분때문에 고심했던지라....자세히는 기억이 안나네요.....화이팅입니다......

---------------------------------------------------------------
Opensource에 기여하는 것이 꿈입니다.
내가 만든 코드를 모두가 사용할 때 까지~

»

정확한지는 모르겠지만...

글쓴이: shint 작성 일시: 화, 2013/09/24 - 2:04오후

IP 대역이 서로 다른 상황에서 서로 통신하기 위해서는 
Virtual Box같은 가상 PC 설치한 후에
xxx.xxx.xxx.254인가? 255인가? 멀티캐스팅인가? 뭔가로 송수신 하면 되던데요. ㅇ_ㅇ;;

홀드 펀칭이니 STUN 이니... 말은 많은데 뭔지는 잘 모르겠네요.

젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

»

P2P통신을 구현해야하는지라..

글쓴이: dhyoon1 작성 일시: 화, 2013/09/24 - 2:45오후

효율적인 통신이 되게 하려면

홀펀칭을 쓰는게 답인거 같더라구요..

열심히 찾아봐야죠 ㅠㅠ

»

구현 방식은

글쓴이: shint 작성 일시: 화, 2013/09/24 - 3:14오후

IP 중계서버를 만들거나
공유기의 포트포워딩을 열어주거나
공유기의 DMZ를 열어주거나
UPNP 를 열어주거나... 다양한 방식이 가능해 보입니다.
DirectPlay 같은 경우는 서버에 클라이언트가 접속하게 되면. 클라이언트를 자동으로 연결해 준다고 하네요. ㅇ_ㅇ;;
플래시도 커뮤니티 서버를 사용하면 그런것이 가능하던데요...

문제는. 임의로 사용자의 포트를 강제로 열고 드나드는것은 위법입니다.

젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

»

P2P가 반드시 효율적이지는 않습니다.. 피어중에

글쓴이: klenui 작성 일시: 화, 2013/09/24 - 5:11오후

P2P가 반드시 효율적이지는 않습니다.. 피어중에 성능이 안좋은 녀석이 있을 수도 있고.. 엉터리 정보를 보낼 수도 있습니다.
P2P의 강점은 네트워크 파괴에 대한 내성과 네트워크 대역폭의 분산입니다..

한국은 네트워크 대역폭의 단가가 비싼편에 속해서 가격면에서 P2P가 이득이 있습니다만 단순히 효율만 놓고 본다면 P2P가 낫다고는 말할수 없습니다.

물론 LAN상황이라면 P2P가 가장 효율적인것 맞습니다.

기술적인 개념 검증이라면 여러모로 연구해 보기 좋은 주제입니다만, 실무에서는 쉬운 길을 어렵게 가는 방법일 수도 있습니다..

 

 

=================================

=================================

=================================

 

 

 

 

 

 

 

반응형


관련글 더보기

댓글 영역