C Multicast Socket

DonConto

Commander
Registriert
Juli 2004
Beiträge
2.220
Hallo!

Problem 1: Ich habe keine Ahnung von C :-)
Problem 2: Ich habe ein Programm, welches ich gerne ans Laufen bringen würde :-)

Beispiel hier:

http://openbook.rheinwerk-verlag.de...ung/Kap11-018.htm#RxxKap11018040003971F01A100

Das dortige Beispiel zeigt eine Broadcast bzw. Multicast Server / Client Anwendung. Mich interessiert nur der Client-Teil (client.c). Mein Server schickt Multicast Pakete mit 600 Byte Größe, die ich gerne auswerten würde. Das client.c Programm auf der Webseite funktioniert insoweit, dass es das Paket erhält und (teilweise) die Daten anzeigt. Das Problem ist, dass aus irgendeinem Grund nur die ersten 3 Byte angezeigt werden. So jedenfalls meine Vermutung.

Im Wireshark sehen die ersten 28 Byte des Multicast Pakets so aus:

534d41 00 000402a0 0000 0001 0244 0010 6069 010e 7142ca5a 002d8974, wobei die ersten 3 Byte die Zeichenfolge SMA ergeben. Bei mir spuckt der Client nur

Antwort #1 vom Server: SMA
Antwort #2 vom Server: SMA
.
.
.
Antwort #10 vom Server: SMA

aus.

Jemand eine Idee, wieso da nicht mehr angezeigt wird?
 
Meine Glaskugel sagt mir, dass im Client-Code ein Fehler vorliegen muss. Es kommen (mindestens) 28 Byte an (kommen die kompletten 600 Byte an?), aber nur 6(!) werden verarbeitet. Ein Bestandteil des Alphabets besteht immer aus zwei Hexadezimalwerten, z.B. S = 53 = 0101 0011.

Schickt der Server immer die selbe Antwort? Bzw. sind die ersten 6 Byte identisch?

Ohne zumindest Ausschnitte des Quellcodes wirds sehr schwierig werden.
 
Weil das 4. Byte den Wert 0 hat. Wenn man eine Bytesequenz als C-String auswertet, dann zählt ein Null-Byte als Terminierungszeichen, das quasi bedeutet: "Hier ist Schluß."


P.S. Nur eine Vermutung, ohne jetzt den Code studiert zu haben.

P.S. #2: Ah ja, scheint auch so zu sein:

Code:
int main (void) {
  int iter = 0;
  int sin_len;
  char message[256];
  int socket;
  struct sockaddr_in sin;
  struct hostent *server_host_name;
  if ((server_host_name = gethostbyname (host_name)) == 0) {
     perror ("gethostbyname");
     exit (EXIT_FAILURE);
  }
  socket = setup_multicast_socket ();
  /* Broadcast-Nachrichten empfangen */
  while (iter++ < 10) {
     sin_len = sizeof (sin);
     if (recvfrom( socket, message, 256, 0,
                  (struct sockaddr *) &sin, &sin_len)==-1) {
        perror ("recvfrom");
    }
    printf ("Antwort #%-2d vom Server: %s\n",
       iter, message);
    sleep (2);
  }
  /* Multicast-Socket aus der Gruppe entfernen */
  if (setsockopt ( socket,
                   IPPROTO_IP,
                   IP_DROP_MEMBERSHIP,
                   &command, sizeof (command)) < 0 ) {
      perror ("setsockopt:IP_DROP_MEMBERSHIP");
  }
  close (socket);
  return EXIT_SUCCESS;
}

Man achte auf die printf-Zeile.
Ergänzung ()

Probier auf Client-Seite mal folgendes:

Code:
int main (void) {
	int iter = 0;
	int sin_len;
	char message[256];
	int socket;
	struct sockaddr_in sin;
	struct hostent *server_host_name;
	if ((server_host_name = gethostbyname (host_name)) == 0) {
		perror ("gethostbyname");
		exit (EXIT_FAILURE);
	}
	socket = setup_multicast_socket ();
	/* Broadcast-Nachrichten empfangen */
	while (iter++ < 10) {
		sin_len = sizeof (sin);
		
		const int received = recvfrom( socket, message, 256, 0,(struct sockaddr *) &sin, &sin_len);
					
		if (received==-1) {
			perror ("recvfrom");
		}
		
		printf ("Antwort #%-2d vom Server (%d bytes):", iter, received);
		
		for(int i=0;i<received;++i)
		{
			printf( " %2X", (unsigned int)message[i] );
		}
		
		printf ("\n" );
		sleep (2);
	}
	/* Multicast-Socket aus der Gruppe entfernen */
	if (setsockopt ( socket,
				IPPROTO_IP,
				IP_DROP_MEMBERSHIP,
				&command, sizeof (command)) < 0 ) {
		perror ("setsockopt:IP_DROP_MEMBERSHIP");
	}
	close (socket);
	return EXIT_SUCCESS;
}

Das sollte die gesamte Message, Byte für Byte (in Hex) ausgeben.
 
Zuletzt bearbeitet:
Danke antred für das Beispiel. Hat nach kleinen Anpassungen funktioniert:

message auf 600 Byte gesetzt und in der for Schleife die Variable ausserhalb deklariert (gcc hat gemeckert deswegen).


Antwort #10 vom Server (600 bytes): 53 4D 41 0 0 4 2 A0 0 0 0 1 2 44 0 10 60 69 1 E 71 42 E6 B4 2 48 51 C3 0 1 4 0 0 0 1B B5 0 1 8 0 0 0 0 0 1 B7 18 98 0 2 4 0 0 0 0 0 0 2 8 0 0 0 0 0 0 0 F 78 0 3 4 0 0 0 0 0 0 3 8 0 0 0 0 0 0 2 78 D0 0 4 4 0 0 0 8 A6 0 4 8 0 0 0 0 0 0 5A AE 60 0 9 4 0 0 0 1D 6 0 9 8 0 0 0 0 0 1 C9 63 68 0 A 4 0 0 0 0 0 0 A 8 0 0 0 0 0 0 0 62 70 0 D 4 0 0 0 3 BB 0 15 4 0 0 0 7 A1 0 15 8 0 0 0 0 0 0 89 AA 8 0 16 4 0 0 0 0 0 0 16 8 0 0 0 0 0 0 0 0 0 0 17 4 0 0 0 0 0 0 17 8 0 0 0 0 0 0 4 4E 80 0 18 4 0 0 0 1 B7 0 18 8 0 0 0 0 0 0 E EC C8 0 1D 4 0 0 0 7 D1 0 1D 8 0 0 0 0 0 0 8B F0 38 0 1E 4 0 0 0 0 0 0 1E 8 0 0 0 0 0 0 0 0 0 0 1F 4 0 0 0 3 D9 0 20 4 0 0 3 80 7D 0 21 4 0 0 0 3 D0 0 29 4 0 0 0 11 87 0 29 8 0 0 0 0 0 0 E0 DC D8 0 2A 4 0 0 0 0 0 0 2A 8 0 0 0 0 0 0 0 0 0 0 2B 4 0 0 0 0 0 0 2B 8 0 0 0 0 0 0 0 0 0 0 2C 4 0 0 0 5 AF 0 2C 8 0 0 0 0 0 0 56 9D C0 0 31 4 0 0 0 12 6D 0 31 8 0 0 0 0 0 0 FA 9B F0 0 32 4 0 0 0 0 0 0 32 8 0 0 0 0 0 0 0 0 0 0 33 4 0 0 0 8 BD 0 34 4 0 0 3 7B 5E 0 35 4 0 0 0 3 B7 0 3D 4 0 0 0 2 8D 0 3D 8 0 0 0 0 0 0 51 80 88 0 3E 4 0 0 0 0 0 0 3E 8 0 0 0 0 0 0 4 FF B0 0 3F 4 0 0 0 0 0 0 3F 8 0 0 0 0 0 0 F D0 98 0 40 4 0 0 0 1 40 0 40 8 0 0 0 0 0 0 6 C7 50 0 45 4 0 0 0 2 D7 0 45 8 0 0 0 0 0 0 59 68 20 0 46 4 0 0 0 0 0 0 46 8 0 0 0 0 0 0 5 FE 38 0 47 4 0 0 0 1 80 0 48 4 0 0 3 83 FA 0 49 4 0 0 0 3 82 90 0 0 0 1 2 4 52 0 0 0 0


Jetzt muss ich das nur noch formatieren :-)
 
DonConto schrieb:
Danke antred für das Beispiel. Hat nach kleinen Anpassungen funktioniert:

message auf 600 Byte gesetzt und in der for Schleife die Variable ausserhalb deklariert (gcc hat gemeckert deswegen).

Huch, ich dachte in C99 dürfen lokale Variablen auch innerhalb von Schleifen deklariert werden?

asdfman, wir brauchen mal deinen Input. :p
 
Ich glaube da hast du Recht, aber:

root@raspi:/opt/smaem# gcc -o client client.c
client.c: In function 'main':
client.c:89:3: error: 'for' loop initial declarations are only allowed in C99 mode
client.c:89:3: note: use option -std=c99 or -std=gnu99 to compile your code

Aber -std=c99 als Parameter für gcc hat nicht funktioniert. Daher hab ich ein int i = 0; reingepackt.

Für mich nur böhmische Dörfer :-)
Ergänzung ()

Wer Lust, Zeit und Laune hat, darf sich gerne melden (PN) um bei der Umsetzung zu helfen. Das Projekt ist reines Hobby und Selbstinteresse. Hintergrund ist die Auswertung von Energiedaten eines EFH. Ziel soll sein die empfangenen Daten dauerhaft zu speichern um sie später auszuwerten.
 
Zurück
Oben