Soluzione per scoprire peer LAN leggeri?


9

Ho creato una libreria per la programmazione puramente multipiattaforma. I miei giochi realizzati con esso funzionano perfettamente su Android, PC, Linux, Mac ecc.

Le funzionalità di rete sono fornite dalla libreria ENET, quindi tutte le comunicazioni tra le mie app non sono compatibili con TCP o UDP, ma solo nel protocollo personalizzato, anche se alla fine si basa sull'UDP.

Non credo sia possibile fare ciò che voglio con ENET, ecco perché chiedo aiuto qui!

Diciamo che ho lo stesso gioco in esecuzione sul mio telefono Android, sul mio laptop e sul mio PC. Sono tutti nella stessa rete wifi, e quindi in una LAN, sia il suo hotspot WiFi (?) Che il router domestico.

Ho bisogno di ognuno di questi 3 colleghi per scoprire gli altri due nella rete. Ciò ha lo scopo solo di trovare l'IP delle app vive nella rete LAN, per poter ospitare giochi multiplayer tra di loro.

Posso solo pensare a un modo efficace per farlo, la trasmissione UDP, attendere le risposte, ma se questa è la soluzione, ho bisogno di qualcosa di piccolo, poiché è l'unico scopo dell'implementazione.

Un altro modo potrebbe essere quello di provare a connettersi a tutti gli IP nella sottorange dell'indirizzo LAN, ma non credo che il sistema operativo sarebbe con me su questo: p


2
Penso che alcune trasmissioni UDP siano la strada da percorrere, e non capisco le tue obiezioni, o è che ENET non supporta le trasmissioni?
Roy T.

Esatto, non può trasmettere solo a colleghi già noti.
Grimshaw,

stackoverflow.com/questions/683624/… Questo influenza una risposta?
Grimshaw,

Risposte:


5

Come molte persone hanno detto, la soluzione sarebbe quella di utilizzare la trasmissione UDP , ma ci sono molti dettagli di implementazione coinvolti. Di recente ho riscontrato lo stesso problema e dopo aver elaborato una soluzione ho realizzato un post sul blog e un progetto di esempio sotto forma di un server / client di chat LAN. Riassumerò quelli qui, ma dovresti verificarli per maggiori dettagli e codice reale.

Ecco come funziona, basato su una descrizione di Lee Salzman, creatore di ENet:

  • Il server di gioco funziona su un socket, come host ENet
  • Il server si collega anche a una porta di "ascolto" nota, come un normale socket UDP (ovvero non un host ENet)
  • Il client invia un messaggio broadcast UDP (cioè IP 255.255.255.255) a quella porta di ascolto e attende le risposte
  • Tutti i server nella LAN riceveranno quel messaggio "scan" e risponderanno. Idealmente, puoi rispondere con la porta su cui è in esecuzione il server di gioco (host ENet); in questo modo non devi avere il tuo server di gioco in esecuzione su una porta fissa)
  • Dopo che il client ha ricevuto alcune risposte, saprà quali server sono presenti. Quindi puoi sceglierne uno a cui connetterti, come un normale peer ENet. A questo punto il client non ha più bisogno del socket "scanner" UDP.

La buona notizia è che ENet fornisce funzioni wrapper per l'utilizzo di socket , in modo da poter fare tutto in ENet. La cattiva notizia è che il wrapper è estremamente sottile; devi conoscere la programmazione dei socket , come ad esempio cosa select()fa. Questo è il motivo per cui ti incoraggio a dare un'occhiata al post sul blog e al progetto di esempio in modo da poter copiare / incollare il codice e risparmiare molto tempo.

Ecco alcune note e insidie ​​che dovresti scegliere di fare la tua implementazione:

  • Il listener / scanner deve essere UDP, quindi è necessario crearli utilizzando enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM)(o SOCK_DGRAMper la semplice programmazione di socket vecchi)
  • Per il "listener" del server, consenti di riutilizzare l'indirizzo della porta utilizzando enet_socket_set_option(socket, ENET_SOCKOPT_REUSEADDR, 1)(o SO_REUSEADDR) in modo che più server possano essere eseguiti sullo stesso IP
  • Per lo "scanner" client, è necessario abilitare le trasmissioni sul socket UDP utilizzando enet_socket_set_option(scanner, ENET_SOCKOPT_BROADCAST, 1)(o SO_BROADCAST), altrimenti non è possibile inviare all'indirizzo di trasmissione. Questa è solo una funzione di sicurezza , per rendere più difficile l'inondazione accidentale della rete.

Purtroppo questa non è esattamente una soluzione "leggera"; il progetto campione arriva a qualche centinaia di LOC. Sarebbe bello se questo fosse impacchettato in una libreria di utility per ENet, ma ho scoperto che per i server di gioco, spesso vuoi inviare alcune informazioni più specifiche del gioco con la risposta del server per renderlo utile, come:

  • Il tipo di gioco (ad es. "Cooperativa", "deathmatch")
  • La "mappa", il "livello" o la "campagna" in esecuzione sul server
  • Il numero di giocatori e il numero massimo di giocatori per il server
  • Qualsiasi altra informazione specifica del gioco che influenzerà la decisione del cliente di connettersi o meno. Pensa ai "browser server" nei giochi e al tipo di informazioni che mostrano.

Questo è esattamente quello che stavo pensando. La radiodiffusione è la strada da percorrere.
Lolums

3

Quando non vuoi lasciare la tua biblioteca, puoi semplicemente usare la forza bruta e tentare di connetterti a ciascuno dei possibili indirizzi. La maggior parte dei prestiti domestici sono reti di Classe C (/ 24) in cui i primi 24 bit dell'indirizzo IP sono uguali e gli ultimi 8 bit differiscono. Quindi hai solo 255 possibili indirizzi IP.

Tuttavia, fare una trasmissione UDP sarebbe l'alternativa più pulita. Basta inviare un pacchetto UDP a 255.255.255.255 e tutti i client dietro lo stesso router lo riceveranno. Possono quindi inviare una risposta all'IP di origine e alla porta di origine del pacchetto per informare il mittente che sono presenti.


2
Per favore, per favore, per favore , per favore, per favore , non forza bruta.
Trevor Powell,

@TrevorPowell ... because ...?
Philipp,

2
Perché è la soluzione sbagliata. Non funzionerà nelle università (che non usano le reti di classe c) o nelle imprese (che di solito non usano le reti di classe c) e il personale IT di entrambi non gradirà molto il carico causato dal fatto che ogni giocatore faccia brute-force tenta di inviare messaggi a tutti gli indirizzi IP della propria rete ogni volta che fanno clic su un pulsante "Aggiorna". È solo una cattiva soluzione al problema . Questa domanda su come individuare potenziali peer senza un server matematico è esattamente a cosa serve la trasmissione. Usa trasmissione. È meglio in ogni modo. :)
Trevor Powell,

1

Puoi dare un'occhiata a DNS-SD / ZeroConf / Avahi / Bonjour / mDNS . È la roba che Apple usa per condividere stampanti, cartelle iTunes e così via, ma è stata adottata altrove. Avahi è la versione open source utilizzata da Linux (non sono sicuro che sia solo Linux), non è sicuro di quanto sia portatile tutto (anche se ci sono implementazioni per la maggior parte delle piattaforme).

Detto questo, è probabilmente più semplice eseguire la trasmissione UDP.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.