[risolto]Chiarimento sul multicast

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
Avatar utente
jack84
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 493
Iscrizione: lunedì 12 febbraio 2007, 11:13

[risolto]Chiarimento sul multicast

Messaggio da jack84 »

Dovrei realizzare una comunicazione di tipo multicast, ma ho qualche problema nel realizzarlo.
Il multicast consente di inviare una pacchetto UDP a più destinatari conteporaneamente sulla base di un unico indirizzo di tipo multicast che rappresenta un insieme indirizzi di destinatari che si sono precedentemente registrati. Fin quando registro un solo utente non ho problemi e il messaggio giunge a destinazione regolarmente. Tuttavia se registro un altro utente e assegno tramite la bind indirizzo ip e porta mi da errore perchè la porta è già usata per ascoltare da l'altro utente, però io necessito di poter riusare quella porta per ascoltare poichè il multicast è realizzato su di essa... Mi domando anche se il multicast funzioni effettivamente solo se si opera su più computer diversi in modo da avere su ciascuno la porta a disposizione.
Qualcuno sa darmi qualche dritta per realizzare il meccanismo...
Ultima modifica di jack84 il venerdì 29 febbraio 2008, 15:32, modificato 1 volta in totale.
Non sempre si può prevedere, ma ci si può sempre preparare
Avatar utente
daemon_nio
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1012
Iscrizione: lunedì 15 gennaio 2007, 14:18
Sesso: Maschile
Località: London
Contatti:

Re: [c] Chiarimento sul multicast

Messaggio da daemon_nio »

ma l'errore è del client?

Ossia, quando lanci il secondo client hai l'errore? In tal caso l'errore sta nel fatto che hai i due client sulla stessa macchina... ma non saprei come risolvere.
Altrimenti se l'errore è sul server non ho capito dove.

P.S. non credo sia un problema di c comunque!
Sempre costruendo qualcosa di nuovo: Matag: The Game
Avatar utente
jack84
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 493
Iscrizione: lunedì 12 febbraio 2007, 11:13

Re: [c] Chiarimento sul multicast

Messaggio da jack84 »

Posto il link dal quale ho preso spunto cosi ci capiamo, mi sono riletto e ho notato di non essere stato tanto chiaro  :P
http://www.tack.ch/multicast/

Il problema che ho io è quando lancio due instanze del server



// open a UDP socket
  sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
  if ( sock < 0 )
    perror("Error creating socket"), exit(0);

  saddr.sin_family = PF_INET;
  saddr.sin_port = htons(4096); // listen on port 4096
  saddr.sin_addr.s_addr = htonl(INADDR_ANY); // bind socket to any interface
  status = bind(sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in));

  if ( status < 0 )
    perror("Error binding socket to interface"), exit(0);

  imreq.imr_multiaddr.s_addr = inet_addr("226.0.0.1");
  imreq.imr_interface.s_addr = INADDR_ANY; // use DEFAULT interface

  // JOIN multicast group on default interface
  status = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
              (const void *)&imreq, sizeof(struct ip_mreq));

  socklen = sizeof(struct sockaddr_in);

  // receive packet from socket
  status = recvfrom(sock, buffer, MAXBUFSIZE, 0,
                    (struct sockaddr *)&saddr, &socklen);

  // shutdown socket
  shutdown(sock, 2);

Nella parte evidenziata quando lancio il secondo server incorre nell'errore perchè il numero di porta è usato già dall'altro server.
Il problema è che senza la bind non credo che il tutto funzioni visto che sul client è specificata la porta di destinazione sulla quale è effettuato il multicast. Quello che mi aspetto di ottenere è che lanciando due instanze del server e successivamente il cliet entrambi ricevano il messaggio
Ultima modifica di jack84 il giovedì 28 febbraio 2008, 21:22, modificato 1 volta in totale.
Non sempre si può prevedere, ma ci si può sempre preparare
Avatar utente
daemon_nio
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1012
Iscrizione: lunedì 15 gennaio 2007, 14:18
Sesso: Maschile
Località: London
Contatti:

Re: [c] Chiarimento sul multicast

Messaggio da daemon_nio »

il mio dubbio è: perché lanciare due server?

Il server è unico, invia pacchetti e basta. La rete li duplica per fare multicasting ma a te cosa importa?
Sempre costruendo qualcosa di nuovo: Matag: The Game
Avatar utente
jack84
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 493
Iscrizione: lunedì 12 febbraio 2007, 11:13

Re: [c] Chiarimento sul multicast

Messaggio da jack84 »

::) Ecco allora mi sa che non ho capito  ::)
Il server esegue un'operazione di recvfrom non vedo dove avviene l'invio :'(
Non dirmi che ho invertito le parti e quello che credevo si occupasse di inviare in realtà riceve (rotfl)
Spiegami un attimo, vome si fa a leggere ciò che è stato inviato al server?
Ultima modifica di jack84 il giovedì 28 febbraio 2008, 21:47, modificato 1 volta in totale.
Non sempre si può prevedere, ma ci si può sempre preparare
Avatar utente
daemon_nio
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1012
Iscrizione: lunedì 15 gennaio 2007, 14:18
Sesso: Maschile
Località: London
Contatti:

Re: [c] Chiarimento sul multicast

Messaggio da daemon_nio »

Codice: Seleziona tutto

// Multicast Server
// written for LINUX
// Version 0.0.2
//
// Change: IP_MULTICAST_LOOP : Enable / Disable loopback for outgoing messages
// 
// Compile : gcc -o server server.c
//
// This code has NOT been tested
// 

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define MAXBUFSIZE 65536 // Max UDP Packet size is 64 Kbyte

int main()
{
   int sock, status, socklen;
   char buffer[MAXBUFSIZE];
   struct sockaddr_in saddr;
   struct ip_mreq imreq;

   // set content of struct saddr and imreq to zero
   memset(&saddr, 0, sizeof(struct sockaddr_in));
   memset(&imreq, 0, sizeof(struct ip_mreq));

   // open a UDP socket
   sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
   if ( sock < 0 )
     perror("Error creating socket"), exit(0);

   saddr.sin_family = PF_INET;
   saddr.sin_port = htons(4096); // listen on port 4096
   saddr.sin_addr.s_addr = htonl(INADDR_ANY); // bind socket to any interface
   status = bind(sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in));

   if ( status < 0 )
     perror("Error binding socket to interface"), exit(0);

   imreq.imr_multiaddr.s_addr = inet_addr("226.0.0.1");
   imreq.imr_interface.s_addr = INADDR_ANY; // use DEFAULT interface

   // JOIN multicast group on default interface
   status = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, 
              (const void *)&imreq, sizeof(struct ip_mreq));

   socklen = sizeof(struct sockaddr_in);

   // receive packet from socket
   status = recvfrom(sock, buffer, MAXBUFSIZE, 0, 
                     (struct sockaddr *)&saddr, &socklen);

   // stampo a video ciò che mi è stato inviato
   printf("%s",buffer);

   // shutdown socket
   shutdown(sock, 2);
   // close socket
   close(sock);

   return 0;
}
Allora quello è il codice del server... come vedi ho aggiunto un'istruzione di printf per stampare a video ciò che il client ha inviato.

Non mi ricordo bene tutte queste strutture del c... le ho usate a suo tempo anche se devo dirti la verità mai per il multicasting ma solo per connessione con socket tra due host.

Il problema che hai tu è: non puoi lanciare due server sullo stesso host. Semplicemente perché non c'è scopo :D

Il server si mette in ascolto di invio di dati e un client glieli invia. Per come è stato costruito il server dopo che ha ricevuto i dati si chiude... si dovrebbe fare un while che rimane in attesa infinita.

Io penso che funzioni così... ogni host che vuole unirsi alla conversazione crea un server e un client: il server ascolta i messaggi che tutti gli altri del gruppo inviano e il client invia i messaggi. Ora il tuo scopo dovrebbe essere di creare i client e i server... ma non credo lo puoi fare dalla stessa macchina altrimenti hai errori nel binding.

Non saprei come fare per evitare errori... se hai la possibilità di usare più computer te lo consiglio... altrimenti vedi un po' in giro come hanno risolto il problema.

In genere si usa modificare la porta di connessione... ma a te trattandosi di multicasting e non di normale comunicazione penso che non puoi fare così, oppure pensarci un po' su prima di progettare.
Sempre costruendo qualcosa di nuovo: Matag: The Game
Avatar utente
jack84
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 493
Iscrizione: lunedì 12 febbraio 2007, 11:13

Re: [c] Chiarimento sul multicast

Messaggio da jack84 »

Ti ringrazio moltissimo per la disponibilità, avevo aggiunto anche io la stampa del buffer nel mio programma, per questo avevo scritto che con un singolo che legge funziona, ma non con più ascoltatori sulla stessa macchina non va e tattandosi di multicast questa cosa dovrebbe andare e non solo su mecchine diverse. Se non altro la comunicazione non deve essere bidirezionale, mi basta che un host possa inviare a molti host registrati. Cerco ancora magari trovo qualcosa di utile.
Non sempre si può prevedere, ma ci si può sempre preparare
Avatar utente
daemon_nio
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1012
Iscrizione: lunedì 15 gennaio 2007, 14:18
Sesso: Maschile
Località: London
Contatti:

Re: [c] Chiarimento sul multicast

Messaggio da daemon_nio »

Secondo me il punto chiave è questa funzione: setsockopt

c'è sia nel server:

Codice: Seleziona tutto

   // JOIN multicast group on default interface
   status = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, 
              (const void *)&imreq, sizeof(struct ip_mreq));
che nel client:

Codice: Seleziona tutto

   // send multicast traffic to myself too
   status = setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP,
                       &one, sizeof(unsigned char));
direi di guardarla bene.

Secondo me dovrebbe funzionare così... un client e un server per ogni macchina, il client che invia i dati il server che li riceve... se leggi nel client questa funzione send multicast traffic to myself too, quindi il server che viene lanciato prima sulla stessa macchina riceve il pacchetto semplicemente perché si trova sulla stessa macchina ed è unito al gruppo multicast. Quindi il client lo manda a se stesso e il server lo stampa. (rileggendomi mi sono spiegato male... ma spero di aver impresso il concetto)

Come ultimo consiglio che ti posso dare e aprire un post anche sulla sezione del forum network... casomai con un link a questo topic, in modo da vedere cosa dicono lì... troverai persone molto più competenti di me sul multicast (vabbè non ci vuole molto per questo  (rotfl))
Ultima modifica di daemon_nio il venerdì 29 febbraio 2008, 12:25, modificato 1 volta in totale.
Sempre costruendo qualcosa di nuovo: Matag: The Game
Avatar utente
jack84
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 493
Iscrizione: lunedì 12 febbraio 2007, 11:13

Re: [c] Chiarimento sul multicast

Messaggio da jack84 »

Ti ringrazio ancora della collaborazione, cercando in rete sono riuscito a trovare un modo per consentire di assegnare la stessa porta più volte in modo che se capita che due istanze girino sulla stessa macchina possono condividere la porta d'ascolto.
Avevi ragione riguardo la setsockopt, è proprio l'istruzione incriminata, non a caso con essa si configurano le opzioni del socket.
L'istruzione è:

Codice: Seleziona tutto

if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) < 0) {
         perror("Reusing ADDR failed");
         return -1;
       }
dove yes è un intero senza segno settato a 1 e sock è il socket d'ascolto del server.
E' sufficente  inserirla subito dopo la creazione del socket, prima del binding in modo che quando viene eseguito il server può ascoltare sulla stessa porta di un altro.
Provare per crede  (good), metti quella e lancia due instanze del server, poi lancia il client e vedrai magicamente che entrambi ricevono il messaggio ;D.
Ultima modifica di jack84 il venerdì 29 febbraio 2008, 13:48, modificato 1 volta in totale.
Non sempre si può prevedere, ma ci si può sempre preparare
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: 0 utenti iscritti e 3 ospiti