2009-04-29 12 views
4

Ich schreibe einen UDP Test Client/Server und ich möchte es durch die Firewall bekommen. Angeblich muss ich nur beide Seiten an die richtige IP und Server senden lassen. Das Erhalten einer IP ist kein Problem, aber wie kann ich den Client einen zufälligen freien Port auswählen lassen und es dem Benutzer melden? Irgendwann würde ich wollen, dass es sich mit einem Matchmaker-Server verbindet, aber im Moment brauche ich einen einfach funktionierenden Prototyp und ich möchte die Portnummer kürzen, damit mein Freund/Tester mir die # via IM schicken kann, damit wir testen können.Wie bekomme ich einen freien Socket-Port? C++

Wie bekomme ich die Portnummer? sorry für die lange desc. Ich merke, Leute sagen mir nicht zu tun, was ich frage, wenn ich nicht eine Beschreibung gebe :(

Antwort

5

Um den hochtechnischen Begriff zu verwenden, ist dies eigentlich ein ziemlich eklig Problem oder sogar ein paar eklige Probleme. Abhängig von der Konfiguration der Firewall werden normalerweise Antworten von einem anderen Endpunkt auf dem IP-Endpunkt zugelassen, wenn die Anforderung kam. Also ... wenn Ihr Freund das UDP-Datagramm unter Verwendung des Systemaufrufs recvfrom() empfängt, empfängt der Adressparameter die IP-Endpunktinformationen, auf die er antworten soll. So sollte das andere Ende in der Lage sein, mit einem sendto() unter Verwendung der gleichen Adressierungsinformationen zu antworten. Etwas wie:

/* 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); 

Die peeraddr auf der anderen Seite wird Ihre externen Adresse oder, richtiger gesagt, die IP-Adresse Ihrer Firewall und die Port-Nummer sein, dass es zu benutzen gewählt haben. Die Portnummer, die Sie in Ihrem Code angeben, unterscheidet sich möglicherweise vollständig von dem Port, an den Ihr Freund Daten senden muss. Letztendlich ist es egal, welchen Port Sie verwenden möchten, da die Firewall möglicherweise an einem völlig anderen Port sendet und empfängt - darum geht es bei Network Address Translation. Ich würde empfehlen, RFC3235 für einige Tipps zu lesen, wie man diese Hürde überwinden kann.

Der beste Ansatz IMHO ist:

  1. Lassen Sie das Betriebssystem einen Port auswählen, indem entweder bind() mit einer Null-Port-Nummer anrufen oder den bind Überspringen insgesamt
  2. der Client die Adressinformationen aus der Steckdose erhalten zu haben Schicht (beispielsweise der fünfte und sechste Argumente recvfrom())
  3. der Client sendet als Reaktion auf den abgerufenen Endpunkt in dem vorherigen Schritt
  4. die Firewall-Konfigurationen, bis die vorherigen Schritte Zwicken WO rk

Natürlich ist all die Magie im letzten Schritt. Wenn Sie NAT deaktivieren oder sicherstellen können, dass die Firewall niemals Ports umschaltet, funktioniert das auch, wenn Sie eine Port-Nummer und bind-hingen. Je nachdem, wie Ihr Betriebssystem eingestellt ist, können Sie unter %WINDIR%\system32\drivers\etc\services (oder /etc/services) nachsehen, welche Portnummern reserviert oder allgemein verwendet werden.

0

Allgemein gesagt - Sie - als Entwickler - wählen Sie den Port.Sie ​​können Ihre Anwendung den Port aus einer Konfigurationsdatei lesen oder Benutzereingaben - aber keine magische Firewall wird Ihnen sagen, welcher Port zu verwenden ist ...

0

Wenn ich Ihre Frage richtig verstehe, bin ich mir nicht sicher, ob es einen Weg gibt, was Sie programmatisch (und sogar Wenn ja, glaube ich nicht, dass es der richtige Ansatz ist.) Ich denke, Sie müssen einen Port finden, der nicht auf dem Servercomputer verwendet wird (und möglicherweise einen anderen oder denselben Port auf dem Clientcomputer, wenn die Kommunikation erfolgt bidirektional) UND dieser Port muss in der Lage sein, Ihre Firewall zu passieren.Ich nehme an, da Sie sagen, "eine IP bekommen ist kein Problem", haben Sie bereits zusammen Haben Sie Ihre Firewall so konfiguriert, dass einige oder alle Ports an einen bestimmten Computer in der Firewall weitergeleitet werden? Wenn dies der Fall ist, ist der von Ihnen gesuchte Port einer Ihrer Weiterleitungen. Sie können nur einen beliebigen auswählen, solange auf diesem Port kein anderer Dienst läuft. Ports unter 1024 sind reserviert, also sollten Sie wahrscheinlich eine höhere Nummer wählen. Sie können ein einfaches Portscanning-Tool wie nmap verwenden, um zu sehen, welche Dienste auf Ihrem Computer an welchen Ports ausgeführt werden, und einen anderen auswählen. Beachten Sie, dass nmap durch Firewalls und verschiedene bind Regeln getäuscht werden kann, wenn Sockets erstellt werden.

0

Ich denke, Sie sind besser dran, einen festen Port zu wählen, anstatt sich auf die vom O/S ausgewählte zufällige Portnummer zu verlassen.

Wenn Sie einen zufälligen Port verwenden, müssen Sie Ihre Firewalleinstellungen jedes Mal ändern, wenn Sie das Programm ausführen.

0

Wenn Sie WINSOCK Check diesen Link verwenden: http://msdn.microsoft.com/en-us/library/aa280717(VS.60).aspx Grundsätzlich haben Sie die Wahl zwischen 2 den Port auf 0 gesetzt und lassen Sie das System weisen Sie einen oder wählten ein gelegentliches man versuchen, den Sockel zu öffnen, wenn es nicht funktioniert versuchen Sie einen anderen (achten Sie darauf, von reservierten Ports zu vermeiden)

0

bind() den Socket, bevor Sie Ihre Daten senden. Geben Sie Port 0 für bind() an, und das Betriebssystem wählt einen nicht verwendeten Port für Sie aus. Sie können dann mit getsockname() herausfinden, welcher Port ausgewählt wurde.