Udp/ip-kommunikation Kann keine Verbindung herstellen
#1
geschrieben 10. März 2005 - 11:58
versuche gerade, eine UDP/IP-Kommunikation (Client <-> Server) zu implementieren. Nur erhält der Server keine Daten von Client.
Hier ein paar Details:
Der Server holt sich mit socket(AF_INET, SOCK_DGRAM, 0) einen Socket und bindet ihn an INADDR_ANY (0.0.0.0). Der Socket wird mit setsockopt() als Broadcasting-Socket parametriert und mit ioctlsocket() non-blocking gesetzt.
Der Client holt sich auch einen Socket und macht ihn non-blocking. Der Socket wird weder mit bind() noch mit connect() gebunden.
Als Empfänger-Adresse erhält der Client die IP-Adresse des Servers. Da ich Server und Client auf demselben Rechner habe laufen lassen, habe ich diese mit gethostname() und queryhost() ermittelt.
Als Port habe ich eine m.E. geeignete Nr. gewählt und in der Firewall auch freigegeben.
Der Server erhält aber keine Daten vom Client (der sendet), recvfrom() gibt immer -1 zurück.
Alternativ habe ich mich mal im inet eingeloggt und die Client-IP meines Netzwerk-Adapters als Server-Adresse verwendet. Nada.
Was mache ich falsch?
Anzeige
#2
geschrieben 10. März 2005 - 12:36
Zitat
Ein ungebundener Socket lässt sich auch mit sendto() nicht nutzen. Du musst ihn schon an mindestens ein Netzwerkinterface binden.
Zitat
Hast du das mal mit einem Sniffer überprüft? Ich glaube nicht, Tim.
Ja, mata ne!
(For sending email please use OpenPGP encryption and signing. KeyID: 0xA0E28D18)
#3
geschrieben 10. März 2005 - 12:49
Auf gamedev.net hat mir jemand Beispielcode gegeben, und hat der Sender weder bind() noch connect() benutzt.
Wenn er das doch tun sollte, welche IP soll er nehmen - INADDR_ANY, oder die des Empfängers?
Ich habe versucht, mir das mit netstat anzusehen, aber der zeigt gar keine UDP-Verbindungen an, weder wenn ich den Server starte (der macht bind()), noch für den Client.
Dann wollte ich mir ethereal holen (Tip von gamedev.net), aber das ist wohl wieder mal ein typisches Linux Geek Projekt: Keine vernünftige Doku, kein vernünftiger Installer, kein GUI. Kotz. Dort gibt es nur ein winpcap.exe ohne weitere Erklärungen. Typisch Open Source, ist nicht meine erste derartige Erfahrung damit. Das Wort "benutzerfreundlich" scheint die zu Übelkeitsanfällen oder Hohngelächter zu reizen.
#4
geschrieben 10. März 2005 - 13:07
Zitat
Die eigene als Source, die des Empfängers als Destination. Das bind() ist dafür zuständig das richtige Interface auszuwählen.
Zitat
Wenn überhaupt dürfte ja wohl nur der Server ein LISTEN auf dem jeweiligen Port anzeigen. UDP ist verbindungslos.
Zitat
Quatsch. Es gibt ein wunderschönes GTK-Interface mit Installer (http://www.ethereal....etup-0.10.9.exe).
Zitat
Ist es zu viel verlangt einfach mal auf die WinPCap-Homepage zu gehen? Dort steht mehr als genug. Und eigentlich braucht man über WinPCap nichts weiter zu wissen, außer daß man es halt braucht, damit auch Ethereal läuft.
Zitat
WinPCap und Ethereal sind benutzerfreundlich, sie suchen sich nur ihre Benutzer etwas genauer aus.
Ja, mata ne!
(For sending email please use OpenPGP encryption and signing. KeyID: 0xA0E28D18)
#5
geschrieben 10. März 2005 - 13:20
Zunächst mal müssen sich doch Client und Server finden. Erst dann werden ihre jew. IPs in den Source und Destination Fields der Daten eingetragen.
Wie finden die sich aber nun?
Momentan macht der Server bind() von INADDR_ANY an einen UPD-Socket. Dann pollt er mit recvfrom().
Der Client() hat sich nur einen UDP-Socket geholt, keinen bind() oder connect() drauf gemacht. Er verwendet als Destination Address die IP des Servers (die ich im Server mit gethostbyname() und queryhost() ermittelt habe).
Der Server wird auch mit netstat in der UDP-Liste als 0.0.0.0:<port> angezeigt.
Trotzdem empfängt er keine Daten vom Client.
Macht der Client auch einen bind(), kriege ich eine Fehlermeldung, weil der Port schon vom Server belegt ist (läuft ja beides auf demselben Rechner).
Die Frage ist, wieso. Natürlich sollte ich mir mal die Client-Pakete mit einem Sniffer anschauen. Per Debugger konnte ich aber feststellen, daß er die Server-IP als Destination einträgt, von daher wunderts mich.
Auf der Ethereal-Seite habe ich mich auf Anhieb nicht zurecht gefunden. Wenn ich auf die "Official Downloads" Seite gehe und dort den deutschen D/L-Server anklicke, lande ich in einem Directory Listing. Da gibt es "all versions" und diverse winpcaps. Unter "all versions" gibt es dutzende von Dateien, am Ende auch ein paar gtk-Dingenskirchen-zips. Wo bitte findet man da den von Dir genannten Link? Und das soll benutzerfreundlich sein? Wieso nicht ein zip mit Windows Installer und alles was man noch benötigt mit drin, und der Installer fragt, welche Komponenten man installieren will? Dieses Gequatsche von "Benutzer aussuchen" klingt da ehrlich gesagt etwas überheblich.
Dieser Beitrag wurde von Aspartam bearbeitet: 10. März 2005 - 13:28
#6
geschrieben 10. März 2005 - 13:36
Zitat
Nein, UDP ist verbindungslos, deshalb gibt es auch keinen Verbindungsaufbau. Der Client weiß nicht mal ob seine Daten überhaupt ankommen, geschweige denn fehlerfrei.
Zitat
sendto() ohne bind() funktioniert nicht.
Zitat
Dann solltest du mal beim Client als Source-Port einen anderen Port wählen.
Zitat
Die Pakete werden zwar erstellt, aber gar nicht gesendet.
Zitat
Und eine ethereal-setup-0.10.9.exe, ganz unten.
Zitat
Genau das macht dieser Installer.
Zitat
Nein. Es geht darum daß die meisten Benutzer gerne Klicki-Bunti-mit-wenig-Optionen mit Benutzerfreundlichkeit verwechseln und sich nebenbei vor schwarzen Fenstern fürchten.
Ja, mata ne!
(For sending email please use OpenPGP encryption and signing. KeyID: 0xA0E28D18)
#7
geschrieben 10. März 2005 - 14:22
danke mal soweit für Deine Hilfe. Ethereal habe ich jetzt. winpcap brauche ich auch, hast Du oben geschrieben.
Trotzdem nochmal zur Server-Client-Verbindung.
Ich möchte im ersten Schritt nur mal erreichen, daß der Server Daten von Client erhält.
Soweit ich es jetzt verstanden habe, kann der Client auf einer beliebigen Adresse+Port senden, er muß nur in Destination Feld die korrekte Empfängeradresse+Port eingetragen haben?
Ergo können Server und Client beide bind() an INADDR_ANY + einen beliebigen geeigneten Port machen (wenn selber Rechner, unterschiedliche Ports)?
Der Client trägt dann in den Daten IP+Port des Servers ein und verschickt sie über seinen gebundenen Socket?
Edit: Ich habe ethereal und winpcap 3.14 installiert, aber ethereal findet die wpcap.dll (oder so ähnlich) nicht, und sie befindet sich auch nicht auf meiner Festplatte.
Edit 2: Es war ein Reboot notwendig ... auf der winpcap-Seite steht, daß es nach der Installation gebrauchsfertig sei ... na egal, jetzt kann ich schnüffeln ...
Edit 3: Ethereal zeigt mir überhaupt keinen UDP Traffic von meinem Programm an.
Dieser Beitrag wurde von Aspartam bearbeitet: 10. März 2005 - 15:38
#8
geschrieben 10. März 2005 - 22:27
Zitat
Ja.
Zitat
Zeigt er sonstigen Traffic im Netz an? Schnüffelst du am richtigen Interface?
Ja, mata ne!
(For sending email please use OpenPGP encryption and signing. KeyID: 0xA0E28D18)
#9
geschrieben 10. März 2005 - 23:42
Ich weiß auch nicht genau, welche Zieladresse ich eigentlich angeben muss, wenn das Ziel auf dem selben Rechner liegt wie die Quelle. 127.0.0.1 funktioniert nicht, die IP meines Netzwerk-Adapters funktioniert nicht, die lokale IP auch nicht (die ich mit gethostname() und gethostbyname() bekomme).
Ich habe übrigens von gamedev.net ein Beispielprogramm bekommen, wo vor dem Senden kein bind() durchgeführt wird. Es sendto() scheint dann auch zu funktionieren, aber ich sehe trotzdem nichts in Ethereal.
Es ist zum Auswachsen.
#10
geschrieben 10. März 2005 - 23:56
Zitat
Das ist ja das altbekannte Verständnisproblem. sendto() ohne bind() scheint zwar zu funktionieren, aber tatsächlich gesendet wird nix.
Zitat
Wenn du's auf dem gleichen Rechner machst, dann geht nur 127.0.0.1. Es sei denn du bist beim Router als DMZ-Rechner eingetragen.
Zitat
Ich weiß ja nicht, wie portabel dein Programm geschrieben ist, aber unter Unix...
Ja, mata ne!
(For sending email please use OpenPGP encryption and signing. KeyID: 0xA0E28D18)
#11
geschrieben 11. März 2005 - 12:35
Dieser Beitrag wurde von Aspartam bearbeitet: 11. März 2005 - 12:40
#12
geschrieben 14. März 2005 - 16:10
Du täuschst Dich bzgl. sendto() ohne bind() bei UPD: In diesem Fall wird einfach ein verfügbarer Port zum Senden ausgewählt. Ich habe das ausprobiert - es ist so.
Mein Programm tut inzwischen.