void* udplisten(void*);

Die Waffel-Strichliste bietet auch eine Netzwerkschnittstelle; darüber lassen sich live wichtige Informationen abrufen:

  • Wie viele Waffeln wurden bereits verkauft?
  • Welches Lied wird gerade gespielt?
  • Wie hoch ist die (geschätzte) Spendensumme?
  • Wann wurde die letzte Waffel verkauft?

Das ganze läuft über UDP, das User Datagram Protocol. Die Funktion udp_listener wird in einem eigenen Thread gestartet. Aber zunächst die Signatur:


027: void* udplisten(void*);

Dieser Prototyp ist im Wesentlichen dadurch bestimmt, dass wir einen Funktionszeiger für die Posix-Funktion pthread_create benötigen, siehe gleich.

In der main-Funktion braucht es noch zwei Variablen:


046:     pthread_t udplistener;
047:     int udplistener_rv;

Und hier geht’s ab: Wir erstellen einen neuen Thread, sodass recvfrom() (Zeile 332) nicht den normalen Benutzerbetrieb stört.


069:     udplistener_rv = pthread_create(&udplistener, NULL, udplisten, NULL);

So, genug der Vorrede, jetzt die Funktion. Wir beginnen mit Deklarationen und sowas…


292: void* udplisten(void* nueksch)
293: {
294:     int sock;
295:     struct sockaddr_in echoserver;
296:     struct sockaddr_in echoclient;
297:     char buffer[BUFFSIZE];
298:     unsigned int clientlen, serverlen;
299:     int received = 0;
300:     char* answer;
301: 
302:     answer = (char*) malloc(sizeof(char) * BUFFSIZE);
303:     if (answer == NULL)
304:     {
305:         fprintf(stderr, "malloc failed @ line %d\n", __LINE__);
306:         exit(-1);
307:     }

Nun legen wir einen UDP-Socket an:


309:     /* Create the UDP socket */
310:     if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
311:     {
312:         fprintf(stderr, "Failed to create socket\n");
313:     }

Da, wo ich diesen Schnipsel herkopiert hab, wird nun die sockaddr_in-Struktur initialisiert; im Wesentlichen vereinbaren wir einen IPv4-Socket und setzen den Port auf PORT==1042


314:     /* Construct the server sockaddr_in structure */
315:     memset(&echoserver, 0, sizeof(echoserver));       /* Clear struct */
316:     echoserver.sin_family = AF_INET;                  /* Internet/IP */
317:     echoserver.sin_addr.s_addr = htonl(INADDR_ANY);   /* Any IP address */
318:     echoserver.sin_port = htons(PORT);                /* server port */

Mit bind() aktivieren wir nun unseren Server-Socket:


320:     /* Bind the socket */
321:     serverlen = sizeof(echoserver);
322:     if (bind(sock, (struct sockaddr *) &echoserver, serverlen) < 0)
323:     {
324:         fprintf(stderr, "Failed to bind server socket\n");
325:     }

Endlosschleife: warte auf eine Anfrage und bearbeite sie…


327:     /* Run until cancelled */
328:     while (1)
329:     {
330:         /* Receive a message from the client */
331:         clientlen = sizeof(echoclient);
332:         if ((received = recvfrom(sock, buffer, BUFFSIZE, 0,
333:                         (struct sockaddr *) &echoclient,
334:                         &clientlen)) < 0)
335:         {
336:             fprintf(stderr, "Failed to receive message\n");
337:         }

Damit die Anfrage auch schön NULL-terminiert ist:


338:         buffer[received] = '';

Die Anfragen bestehen aus einem string, der folgenden Text enthält:

  • qWaffelCount
  • qSpendenSumme
  • qLastWaffel
  • qSong

Die Anfrage steht in buffer und wird mittels strcmp überprüft; dann wird mit sprintf die Antwort zusammengeschustert:


340:         sprintf(answer, "---");
341:         if (strcmp(buffer, "qWaffelCount") == 0)
342:             sprintf(answer, "Bisher verkaufte Waffeln: %d\n", qWaffelCount());
343:         if (strcmp(buffer, "qSpendenSumme") == 0)
344:             sprintf(answer, "Aktuelle Spendensumme: %.2f Euro\n", 0.42*qWaffelCount());
345:         if (strcmp(buffer, "qLastWaffel") == 0)
346:             sprintf(answer, "Letzte Waffel: %s", asctime(qLastWaffel()));

Das aktuelle Musikstück kennt mocp, zu dem wir eine Pipe aufbauen:


347:         if (strcmp(buffer, "qSong") == 0)
348:         {
349:             FILE* fpipe;
350:             char* command="mocp -i | grep ^Title";
351:             char line[256];
352: 
353:             if ( !(fpipe = (FILE*)popen(command, "r")) )
354:             {
355:                 perror("Problems with pipe");
356:                 exit(1);
357:             }
358: 
359:             while ( fgets( line, sizeof line, fpipe))
360:             {
361:                 sprintf(answer, "Aktuelles Lied: %s", line);
362:             }
363:             pclose(fpipe);
364:         }

Bevor es funktionierte, gab es hier eine Ausgabe:


366:         /*
367:         fprintf(stderr, "Client connected: %s\n", inet_ntoa(echoclient.sin_addr));
368:         fprintf(stderr, "Q: %s\n", buffer);
369:         fprintf(stderr, "A: %s\n", answer);
370:         */

Mit sendto schicken wir die Antwort zurück, dann geht die Schleife wieder von vorn los.


372:         /* Send the message back to client */
373:         sendto(sock, answer, strlen(answer), 0, (struct sockaddr *) &echoclient, sizeof(echoclient));
374:     }
375: 
376:     return NULL;
377: }

Kategorie: Allgemein, Linux Kommentare deaktiviert für void* udplisten(void*);

Kommentarfunktion ist deaktiviert.

Zur Werkzeugleiste springen