가벼운 LAN 피어 검색을위한 솔루션?


9

크로스 플랫폼 프로그래밍을위한 라이브러리를 만들었습니다. 내 게임은 Android, PC, Linux, Mac 등에서 잘 실행됩니다.

네트워킹 기능은 ENET 라이브러리에서 제공되므로 내 응용 프로그램 간의 모든 통신은 TCP 또는 UDP와 호환되지 않지만 사용자 정의 프로토콜에서만 가능하며 궁극적으로는 UDP를 기반으로합니다.

ENET으로 원하는 것을 할 수 있다고 생각하지 않으므로 여기에 도움을 요청하십시오!

내 안드로이드 폰, 랩톱 및 PC에서 동일한 게임을 실행한다고 가정 해 보겠습니다. Wi-Fi 핫스팟 (?)이든 가정용 라우터이든 모두 동일한 Wi-Fi 네트워크에 있으므로 LAN에 있습니다.

네트워크에서 다른 두 사람을 발견하려면 3 명의 동료가 각각 필요합니다. 이것은 LAN 네트워크에서 살아있는 앱의 IP를 찾아서 그들 사이에 멀티 플레이어 게임을 호스팅 할 수 있도록하기위한 것입니다.

이 작업을 수행하는 효과적인 방법 중 하나 인 UDP 브로드 캐스트, 대기 응답 만 생각할 수 있지만 솔루션 인 경우 구현의 유일한 목적이므로 작은 것이 필요합니다.

다른 방법은 LAN 주소 하위 범위의 모든 IP에 연결하려고 시도 할 수 있지만 OS가 나와 함께 있다고 생각하지 않습니다 .p


2
나는 몇 가지 UDP 브로드 캐스트가 갈 길이라고 생각하며 이에 대한 귀하의 반대 의견을 이해하지 못합니까, 아니면 ENET이 브로드 캐스트를 지원하지 않는 것입니까?
Roy T.

정확히는 그렇지 않습니다. 이미 알려진 동료에게만 브로드 캐스트 할 수 있습니다.
Grimshaw

stackoverflow.com/questions/683624/… 이것이 답변에 영향을 줍니까?
그림 쇼

답변:


5

많은 사람들이 말했듯이 해결책은 UDP broadcast 를 사용하는 것이지만 구현 세부 사항이 많이 있습니다. 나는 최근에 같은 문제에 부딪 쳤고 해결책을 찾은 후에 블로그 게시물샘플 프로젝트를 만들었습니다. LAN 채팅 서버 / 클라이언트 형태의 를 . 여기에 그것들을 요약 할 것이지만, 자세한 내용과 실제 코드를 확인하십시오.

ENet의 창시자 인 Lee Salzman 의 설명 에 따라 작동 방식은 다음과 같습니다 .

  • 게임 서버는 하나의 소켓에서 ENet 호스트로 실행됩니다.
  • 서버는 일반 UDP 소켓 (예 : ENet 호스트가 아님)으로 알려진 "수신 된"포트에 바인딩합니다.
  • 클라이언트는 UDP 브로드 캐스트 메시지 (예 : IP 255.255.255.255)를 해당 청취 포트로 보내고 응답을 기다립니다.
  • LAN의 모든 서버는 해당 "검색 중"메시지를 수신하고 응답합니다. 이상적으로 게임 서버 (ENet 호스트)가 실행중인 포트로 응답 할 수 있습니다. 그렇게하면 고정 포트에서 게임 서버를 실행할 필요가 없습니다)
  • 클라이언트가 응답을 받으면 어떤 서버가 있는지 알 수 있습니다. 그런 다음 일반 ENet 피어로 연결하기 위해 이들 중 하나를 선택할 수 있습니다. 이 시점에서 클라이언트는 더 이상 UDP "스캐너"소켓이 필요하지 않습니다.

좋은 소식은 ENet이 소켓 사용을위한 래퍼 기능을 제공 하므로 ENet에서 모든 것을 수행 할 수 있다는 것입니다. 나쁜 소식은 포장지가 매우 얇다는 것입니다. 당신에 대해 알고해야합니다 소켓 프로그래밍 , 같은 것과 select()않습니다. 그렇기 때문에 코드를 복사 / 붙여 넣기하고 많은 시간을 절약 할 수 있도록 블로그 게시물샘플 프로젝트를 살펴 보는 것이 좋습니다 .

다음은 자체 구현을 선택해야 할 몇 가지 참고 사항과 함정입니다.

  • 리스너 / 스캐너가 있어야 사용을 만들 필요가 있으므로, UDP 수 enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM)(또는 SOCK_DGRAM평범한 오래된 소켓 프로그래밍을위한)
  • 서버 "리스너"의 경우 여러 서버가 동일한 IP에서 실행될 수 있도록 enet_socket_set_option(socket, ENET_SOCKOPT_REUSEADDR, 1)(또는 SO_REUSEADDR)를 사용하여 포트 주소를 재사용 할 수 있습니다.
  • 클라이언트 "스캐너"의 경우 enet_socket_set_option(scanner, ENET_SOCKOPT_BROADCAST, 1)(또는 SO_BROADCAST)를 사용하여 UDP 소켓에서 브로드 캐스트를 활성화해야합니다 . 그렇지 않으면 브로드 캐스트 주소로 보낼 수 없습니다. 이것은 실수로 네트워크에 플러딩하기 어렵게하기 위한 안전 기능 입니다.

불행히도 이것은 정확히 "경량"솔루션이 아닙니다. 샘플 프로젝트는 모두 수백 개의 LOC에서 작동합니다. 이것이 ENet의 유틸리티 라이브러리에 패키지되어 있으면 좋을 것입니다. 그러나 게임 서버의 경우 서버 응답과 함께 더 많은 게임 관련 정보를 보내서 유용하다는 것을 알았습니다.

  • 게임 유형 (예 : "co-op", "deathmatch")
  • 서버가 실행중인 "지도", "레벨"또는 "캠페인"
  • 서버의 플레이어 및 최대 플레이어 수
  • 클라이언트의 연결 결정에 영향을 줄 다른 게임 관련 정보. 게임에서 "서버 브라우저"와 그들이 보여주는 정보의 종류에 대해 생각하십시오.

이것이 바로 내가 생각한 것입니다. 방송은 갈 길입니다.
Lolums

3

라이브러리를 떠나고 싶지 않을 때는 무차별 대입을 사용하여 가능한 각 주소에 연결을 시도하면됩니다. 대부분의 홈 LAN은 IP 주소의 첫 24 비트가 같고 마지막 8 비트가 다른 Class-C 네트워크 (/ 24)입니다. 따라서 255 개의 가능한 IP 주소 만 있습니다.

그러나 여전히 UDP 브로드 캐스트를 수행하는 것이 더 확실한 대안입니다. UDP 패킷을 255.255.255.255로 보내면 동일한 라우터 뒤에있는 모든 클라이언트가이를받습니다. 그런 다음 패킷의 소스 IP 및 소스 포트에 응답을 보내 발신자에게 자신이 있음을 알릴 수 있습니다.


2
제발 제발 제발 제발 제발 제발하시기 바랍니다 .
트레버 파월

@TrevorPowell ... 왜냐하면 ...?
Philipp

2
잘못된 해결책이기 때문입니다. 대학 (클래스 -c 네트워크를 사용하지 않는) 또는 비즈니스 (일반적으로 클래스 -c 네트워크를 사용하지 않는)에서는 작동하지 않으며 IT 직원은 모든 플레이어의 brute-force는 '새로 고침'버튼을 클릭 할 때마다 네트워크의 모든 IP 주소로 메시지를 보내려고합니다. 문제에 대한 나쁜 해결책 일뿐 입니다. Mathmaking 서버없이 잠재적 인 동료를 찾는 문제는 정확하게 방송입니다. 방송을 사용하십시오. 모든면에서 더 좋습니다. :)
Trevor Powell

1

DNS-SD / ZeroConf / Avahi / Bonjour / mDNS를 살펴볼 수 있습니다 . Apple이 프린터, iTunes 폴더 등을 공유하는 데 사용하는 기능이지만 다른 곳에서 채택되었습니다. Avahi는 Linux가 사용하는 오픈 소스 버전이며 (리눅스인지 확실하지 않음) 전체가 얼마나 이식 가능한지 확실하지 않습니다 (대부분의 플랫폼에는 구현이 있지만).

모든 것을 말했지만, UDP 브로드 캐스트를하는 것이 더 쉬울 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.