Domanda

Sto scrivendo un client / server di test UDP e voglio farlo passare attraverso il firewall. Presumibilmente tutto ciò che devo fare è inviare entrambe le parti all'IP e al server corretti. Ottenere un IP non è un problema, ma come faccio a far scegliere al client una porta libera casuale e segnalarla all'utente? Alla fine vorrei che si connettesse a un server matchmaker, ma in questo momento ho bisogno di un semplice prototipo funzionante e vorrei calcolare il numero di porta in modo che il mio amico / tester possa inviarmi il # via IM in modo che possiamo testare.

Come ottengo il numero di porta? scusa per la lunga discesa. Noto che le persone mi dicono di non fare quello che sto chiedendo quando non do una descrizione :(

È stato utile?

Soluzione

Per usare il termine altamente tecnico, questo è in realtà un problema piuttosto icky o anche un paio di problemi icky. A seconda della configurazione del firewall, in genere consentirà le risposte da un altro endpoint sull'endpoint IP da cui proviene la richiesta. Quindi ... se un tuo amico riceve il datagramma UDP usando qualcosa come la chiamata di sistema recvfrom () , il parametro address riceverà le informazioni dell'endpoint IP a cui rispondere. Quindi l'altra estremità dovrebbe essere in grado di rispondere con un sendto () utilizzando le stesse informazioni di indirizzamento. Qualcosa del tipo:

/* initiator */
struct sockaddr_in hisaddr;
memset(&hisaddr, 0, sizeof(hisaddr));
hisaddr.sin_addr.s_addr = htonl(target_ip);
hisaddr.sin_port = htons(target_port);
sendto(sd, msg_ptr, msg_sz, 0, (struct sockaddr*)&hisaddr, sizeof(hisaddr));

/* receiver */
struct sockaddr_in peeraddr;
socklen_t peer_sz = sizeof(peeraddr);
recvfrom(sd, buf_ptr, buf_sz, 0, (struct sockaddr*)&peeraddr, &peer_sz);
/* build response */
sendto(sd, msg_ptr, msg_sz, 0, (struct sockaddr*)&peeraddr, peer_sz);

Il peeraddr dall'altra parte sarà il tuo indirizzo esterno o, più correttamente, l'indirizzo IP del tuo firewall e il numero di porta che ha scelto di usare. Il numero di porta specificato nel codice potrebbe essere completamente diverso dalla porta a cui il tuo amico dovrebbe inviare i dati. In definitiva, potrebbe non importare quale porta scegli di utilizzare poiché il firewall potrebbe inviare e ricevere su una porta completamente diversa: questo è ciò che Network Address Translation è tutto. Consiglierei di leggere RFC3235 per alcuni suggerimenti su come superare questo ostacolo.

L'approccio migliore per IMHO è:

  1. Consenti al sistema operativo di scegliere una porta chiamando bind () con un numero di porta zero o saltando del tutto il bind
  2. Avere il client ricevere le informazioni sull'indirizzo dal layer socket (ad esempio, il quinto e il sesto argomento su recvfrom () )
  3. Il client invia la risposta all'endpoint recuperato nel passaggio precedente
  4. Modifica le configurazioni del firewall fino a quando i passaggi precedenti non funzionano

Ovviamente, tutta la magia è nell'ultimo passo. Se puoi disabilitare NAT o assicurarti che il firewall non cambierà mai le porte, allora anche inchiodare un numero di porta e associare funzionerà. Potresti dare un'occhiata a % WINDIR% \ system32 \ drivers \ etc \ services (o / etc / services a seconda della tua inclinazione del sistema operativo) per avere un'idea di quali numeri di porta sono riservati o generalmente utilizzati.

Altri suggerimenti

In generale - tu - come sviluppatore - scegli la porta. Puoi impostare l'applicazione in modo che legga la porta da un file di configurazione o dall'input dell'utente, ma nessun firewall magico ti dirà quale porta utilizzare ...

Se capisco correttamente la tua domanda, non sono sicuro che ci sia un modo per fare ciò che vuoi programmaticamente (e anche se c'è, non penso che sia l'approccio giusto). Penso che sia necessario trovare una porta che non è in uso sulla macchina server (e forse una porta diversa o uguale sulla macchina client, se la comunicazione è bidirezionale) E quella porta deve essere in grado di passare attraverso il firewall . Presumo dato che dici "ottenere un IP non è un problema", hai già configurato il firewall per inoltrare alcune o tutte le porte a un computer specifico all'interno del firewall? In tal caso, la porta che cerchi è una di quelle che hai inoltrato. Puoi semplicemente sceglierne uno arbitrario, a condizione che nessun altro servizio sia in esecuzione su quella porta. Le porte inferiori a 1024 sono riservate, quindi probabilmente vuoi scegliere un numero più alto di quello. Puoi utilizzare un semplice strumento di portscanning come nmap per vedere quali servizi sono in esecuzione sul tuo computer su quali porte e scegliere un altro uno. Si noti che nmap può essere ingannato dai firewall e da varie regole bind quando vengono creati i socket.

Penso che sia meglio scegliere una porta fissa piuttosto che fare affidamento sul numero di porta casuale scelto dall'O / S.

Se si utilizza una porta casuale, è necessario modificare le impostazioni del firewall ogni volta che si esegue il programma.

Se stai usando WINSOCK controlla questo link: http://msdn.microsoft.com/en-us /library/aa280717(VS.60).aspx Fondamentalmente hai 2 opzioni per impostare la porta su 0 e lasciare che il sistema te ne assegni una o ne scelga una casuale provi ad aprire il socket se non funziona provane un'altra (assicurati di evitare le porte riservate)

bind () il socket prima di inviare i dati. Specifica la porta 0 per bind () e il sistema operativo sceglierà una porta non utilizzata per te. È quindi possibile utilizzare getsockname () per scoprire quale porta è stata scelta.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top