udp-socket empfängt nichts
-
Gruezi Cler
Ich stelle die Frage hier im allgemeinen C-Forum, weil die Socketgeschichten zu 90% komatibel zwischen den Betriebsystemen sind. In meinem Code sind ein paar windows-socket aufrufe drinnen - bitte hängt euch nicht daran auf.
Ich hab das alles am Anfang auch unter Linux probiert. Das Programm soll nur einen UDP-Socket öffnen und dann zehnmal hintereinander Pakete vom Port 1900 empfangen und den Payload davon anzeigen, aber er empfängt einfach nichts.
- Unter netstat sehe ich wie mein Programm auf dem richtigen Port lauscht - aber er zeigt nichts an - bleibt immer bei dem recvfrom()-call stehen.
- Ich generiere UDP-Datagramme für den Port 1900 mit einem packet-generator unter linux und schicke sie intervallweise an meinen Rechner.
- Ich sehe im Wireshark das die Pakete am richtigen Port ankommen (und dass die in Ordnung sind) - aber das Programm zeigt nichts an!Hier mein Programm:
#include <winsock2.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <iphlpapi.h> #include <errno.h> #pragma argsused int main(void) { WSADATA wsaData; SOCKET upnp_sock; int i=0; int j=0; int bytes=0; int remo_addr_len; struct sockaddr_in remo_addr; struct sockaddr_in listen_addr; char buff[500]; WSAStartup(MAKEWORD(2, 2), &wsaData) ; upnp_sock = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_IP, NULL, 0, 0); printf("\nSOCKET ERROR:%i\n",WSAGetLastError()); listen_addr.sin_addr.s_addr = inet_addr("192.168.0.5"); listen_addr.sin_port = htons(1900); listen_addr.sin_family = AF_INET; bind(upnp_sock, (struct sockaddr*) &listen_addr, sizeof(listen_addr)); printf("\nBIND ERROR:%i\n",WSAGetLastError()); printf("Versuche irgendetwas zu empfangen...\n"); remo_addr_len = sizeof(remo_addr); while (j<10) { i=0; bytes=recvfrom(upnp_sock, &buff, 30, 0, (struct sockaddr *) &remo_addr, &remo_addr_len); if (bytes == -1) { printf("\nRECVFROMERROR:%i\n",WSAGetLastError()); } printf("Bytes:%d\n", bytes); buff[bytes]='\0'; bytes=0; while (buff[i] != '\0' ) { printf("%c", buff[i++]); } printf("\n\n#############\n\n"); memset(&buff, '\0', sizeof(buff)-1); j++; } printf("Feddish\n"); closesocket (upnp_sock); getchar(); return 0; }
-
cyanrigger schrieb:
listen_addr.sin_addr.s_addr = inet_addr("192.168.0.5");
probier mal mit INADDR_ANY
-
jop, probiert - empfängt aber immer noch nüx
Hier mal eins von den Paketen die generiert und gesendet werden (aber ich bin mir recht sicher, dass das passt):
Internet Protocol, Src: 192.168.0.3 (192.168.0.3), Dst: 192.168.0.5 (192.168.0.5) Version: 4 Header length: 20 bytes Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00) 0000 00.. = Differentiated Services Codepoint: Default (0x00) .... ..0. = ECN-Capable Transport (ECT): 0 .... ...0 = ECN-CE: 0 Total Length: 206 Identification: 0x0000 (0) Flags: 0x00 0... = Reserved bit: Not set .0.. = Don't fragment: Not set ..0. = More fragments: Not set Fragment offset: 0 Time to live: 32 Protocol: UDP (0x11) Header checksum: 0x18c7 [correct] [Good: True] [Bad : False] Source: 192.168.0.3 (192.168.0.3) Destination: 192.168.0.5 (192.168.0.5) User Datagram Protocol, Src Port: 26002 (26002), Dst Port: 1900 (1900) Source port: 26002 (26002) Destination port: 1900 (1900) Length: 186 Checksum: 0x0000 (none) Good Checksum: False Bad Checksum: False Hypertext Transfer Protocol Data (178 bytes) ..
-
mach mal, bevor du listen_addr initialisierst, die ganze struct mit 'memset' platt.
ausserdem sagst du bei 'recvfrom', dass du nur 30 bytes haben willst. das passt auch nicht so ganz.
und dann sollteste vielleicht mal den rüchgabewert von 'bind' auswerten.
-
mach mal, bevor du listen_addr initialisierst, die ganze struct mit 'memset' platt.
Meinst du so:
memset(&listen_addr, '\0', sizeof(listen_addr)); memset(&remo_addr, '\0', sizeof(remo_addr));
Hab ich probiert - ändert leider nix.
recvfrom hab ich mal auf 500bytes geschraubt - hätte ja aber auch bei 30bytes schon was empfangen sollen... empfangen hat er trotzdem nix.
Und der Rückgabewert von bind() und socket() ist immer '0'. Das ist ja okay.
Bin echt langsam am verzweifeln.
-
warum steht da eigentlich was von "Hypertext Transfer Protocol"?
-
dann ändern wir nochmal:
cyanrigger schrieb:
... upnp_sock = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_IP, NULL, 0, 0); ...
in:
... upnp_sock = socket (AF_INET, SOCK_DGRAM, 0); if (upnp_sock == INVALID_SOCKET) { printf ("shit..."); exit(0); } ...
oder du machst in deiner zeile aus dem IPPROTO_IP einfach IPPROTO_UDP.
irgendwas davon muss doch klappen...
-
stroh schrieb:
warum steht da eigentlich was von "Hypertext Transfer Protocol"?
da hat wireshark wohl 'nen http-header in den nutzdaten gefunden.
-
und wenn trotzdem alles nicht will, dann bau deinen sender um, so dass er UDP checksums mitsendet. die sind zwar optional, aber man weiss ja nie....
-
warum steht da eigentlich was von "Hypertext Transfer Protocol"?
Das macht der weil das übern Port 1900 geht. Das läuft so UPnP-Zeuch drüber - auf jeden Fall was mit HTTP-Nutzlast - so nimmt er halt an die Nutzlast wär hier auch HTTP-Stuff..
Ich hab alles probiert *-freak
Also keine Fehler bei socket().
Leider hat nichts geklappt - ich verstehs ja selber nicht. Is ja eigentlich keine rocket-science. Stinknormaler sockel halt, geht halt aber net. :|
-
das IPPROTO_IP in WSASocket-aufruf ist aber definitiv falsch, wenn du UDP pakete empfangen willst.
-
das IPPROTO_IP in WSASocket-aufruf ist aber definitiv falsch, wenn du UDP pakete empfangen willst.
Nee, eigentlich passt das schon. IP is ja eine Schicht höher als UDP. UDP-Datagramme sind also in IP-Paketen eingekapselt.
-
probier mal so:
#include <windows.h> #include <winsock.h> #include <stdio.h> #define PORT 1900 void fail (char *s) { printf ("failed due to %s\n", s); exit (0); } int main () { WSADATA wsaData; struct sockaddr_in sin; SOCKET sock; if (0 != WSAStartup (0x0202, &wsaData)) fail ("WASStartup error"); sock = socket (AF_INET, SOCK_DGRAM, 0); if (sock == INVALID_SOCKET) fail ("socket error"); memset (&sin, 0, sizeof(struct sockaddr_in)); sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = htons(PORT); sin.sin_family = AF_INET; if (SOCKET_ERROR == bind (sock, (struct sockaddr*)&sin, sizeof(struct sockaddr_in))) fail ("bind error"); for (;;) { char buff[1500]; int r = recv (sock, buff, sizeof(buff), 0); switch (r) { case SOCKET_ERROR: fail ("recv: error"); case 0: fail ("recv: socket closed"); default: printf ("recv: %d bytes rx'd\n", r); } } }
und zum testen das (und nicht so'ne doofe linux box): http://www.simplecomtools.com/reg_start5.html
(zum downloaden einfach irgendwelchen schrott eintragen)
-
Ok, ich hab noch ein bisschen rumprobiert - und es lag am pktgen. Dem muss ich explizit die Empfänger-MAC-Addresse mitteilen, das er sonst die das Feld mit Nullen zuschreibt. Ein ziemlicher Schwachsinn wie ich finde, denn normalerweise sollte das doch der Switch erledigen soll doch das Feld einfach offen lassen. Wär für mich zumindest logisch.
Das hab ich gecheckt als ichs mit "netcat" probiert hab und dann die Messages einwandfrei ankamen...naja.Mein Problem ist jetzt ein anderes, denn das war ja nur das Vorspiel
Ich will eigentlich Multicasts von einem Gerät empfangen, sone Multimediabox. Die sendet SSDP-Multicasts auf die Adresse 239.255.255.250 und Port 1900. Also fast identische Pakete - aber halt Multicasts.
Und die kann mein Programm immer noch nicht empfangen - warum auch immer - denn das ist ja eigentlich auch Sache vom Switch die auf jede(viele) Adressen im Netz weiterzuleiten.
Vielleicht weiss dazu jemand mehr, wie ich das mit sockets umsetzen kann.
Bei googl€ sind Infos das sehr rar gesät.
-
musstu mit setsockopt und IP_ADD_MEMBERSHIP den empfang von multicast-frames einschalten.
-
Ah, ja danke - hab dann den Link http://www.tack.ch/multicast/ gefunden. Da ist sogar ein Stückchen Kot mit dabei, den ich dann mal ausgeschlachtet habe.
Hat gleich auf Anhieb funktioniert (endlich mal was) und ich habe die ersten Multicasts empfangen. Der "erste Kontakt" ist also endlich geglückt
Danke nochmal an alle freaks