Ich habe ein Verständnisproblem beim Einlesen von UDP-Multicast-Paketen
unter Windows 7 mit Mingw.
Beim Start meines Programms gibt es immer wieder "Startschwierigkeiten",
die ich mir nicht erklären kann. Nur das wiederholte Starten der Routine
search_udp() aus main() führt irgendwann zum Erfolg. Läuft die
Endlosschleife einmal, ist alles ok und die Ausgaben sind zu 100%
vergleichbar mit Wireshark.
Doch was führt zu diesen Startschwierigkeiten?
Ausprobiert habe ich es in zwei völlig unterschiedlichen
Netzwerkumgebungen, doch das beobachtete Verhalten ist sehr ähnlich.
Eine typische Ausgabe des Programms ist:
1 | syncing ................................ synced
|
2 | M-SEARCH * HTTP/1.1
|
3 | HOST: 239.255.255.250:1900
|
4 | MAN: "ssdp:discover"
|
5 | MX: 5
|
6 | ST: urn: (usw)
|
Das Programm soll zunächst nur alle UDP-Pakete an 239.255.255.250 auf
Port 1900 anzeigen. Wie gesagt, das Programm funktioniert soweit, nur
warum der Start so holperig ist und immer viele fehlerhafte
Startversuche hinter syncing mit "." angezeigt werden, ist mir absolut
unklar. Ich finde auch keine Informationen im Netz, aber wahrscheinlich
suche ich mit den falschen Begriffen.
Natürlich habe ich mit Wireshark geprüft, dass während der
Startschwierigkeiten auch Pakete gesendet werden, die angezeigt werden
sollten...
1 | #include <WinSock2.h>
|
2 | #include <WS2tcpip.h>
|
3 | #include <iostream>
|
4 |
|
5 | #define MAX_SYNC_TRIES 600
|
6 | #define SYNC_LENGTH_SEC 2
|
7 |
|
8 | int search_udp();
|
9 |
|
10 | int main()
|
11 | {
|
12 | int i, ret;
|
13 | printf("syncing .");
|
14 | fflush(stdout);
|
15 | for(i=0; i<MAX_SYNC_TRIES; i++) {
|
16 | ret=search_udp(); // try function
|
17 | if (ret==0)
|
18 | i=MAX_SYNC_TRIES*2; // returned successful and ends loop
|
19 | else
|
20 | printf("."); // show next try
|
21 | fflush(stdout);
|
22 | }
|
23 | if (i<MAX_SYNC_TRIES*2)
|
24 | printf("\nERROR: no sync successful\n");
|
25 | return 0;
|
26 | }
|
27 |
|
28 |
|
29 | int search_udp()
|
30 | {
|
31 | WSAData wsaData;
|
32 | SOCKET sock;
|
33 | SOCKADDR_IN sockAddr;
|
34 | ip_mreq mreq;
|
35 | char buf[1555];
|
36 | unsigned long arg=0;
|
37 | WSAStartup(0x0202, &wsaData);
|
38 | sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
39 | if(sock == INVALID_SOCKET)
|
40 | printf("socket() error\n");
|
41 | sockAddr.sin_family = AF_INET;
|
42 | sockAddr.sin_addr.s_addr = INADDR_ANY;
|
43 | sockAddr.sin_port = htons(1900); // <============= multicast_port
|
44 | if(bind(sock, (sockaddr*)&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR)
|
45 | printf("bind() error: %d\n", WSAGetLastError());
|
46 | mreq.imr_multiaddr.s_addr = inet_addr("239.255.255.250"); // <============= multicast_address
|
47 | mreq.imr_interface.s_addr = INADDR_ANY;
|
48 | if(setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mreq, sizeof(mreq)) == SOCKET_ERROR)
|
49 | printf("setsockopt() error: %d\n", WSAGetLastError());
|
50 |
|
51 | // try SYNC_LENGTH_SEC seconds to get any answer
|
52 | time_t timetotry = time(NULL)+SYNC_LENGTH_SEC;
|
53 | while(arg==0){
|
54 | if(ioctlsocket ( sock, FIONREAD, &arg) == SOCKET_ERROR)
|
55 | printf("ioctlsocket() error\n");
|
56 | if (time(NULL)>=timetotry) {
|
57 | closesocket(sock);
|
58 | WSACleanup ();
|
59 | return 1; // not successful synced
|
60 | }
|
61 | }
|
62 | printf(" synced\n", arg);
|
63 | fflush(stdout);
|
64 |
|
65 | // now socket is synced
|
66 | while(1){ // endless
|
67 | memset(buf, 0, sizeof(buf));
|
68 | if(recvfrom(sock, buf, sizeof(buf), 0, NULL, NULL) == SOCKET_ERROR)
|
69 | printf("recvfrom() error\n");
|
70 | if((buf[0] == 'M') || (buf[0] == 'N')) {// only M-SEARCH and NOTIFY
|
71 | printf("%s\n", buf);
|
72 | fflush(stdout);
|
73 | }
|
74 | }
|
75 | closesocket(sock);
|
76 | WSACleanup ();
|
77 | return 0;
|
78 | }
|