Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - Client Server - Passare array di puntatori a char
Forum - C/C++ - Client Server - Passare array di puntatori a char

Avatar
MagoAntò (Normal User)
Rookie


Messaggi: 42
Iscritto: 07/02/2009

Segnala al moderatore
Postato alle 12:41
Sabato, 07/02/2009
Ciao a tutti!
Sono alle primissime armi con la programmazione C e sto cercando di creare una semplice applicazione client-server. Il mio problema è il seguente: riesco a far comunicare client e server ma non riesco a fare in modo che il server invii al client un array di puntatori a caratteri. In pratica, dovrei creare un'applicazione per la gestione di una pizzeria; il client invia un intero al server che, a sua volta, deve trasmettere al client un intero array di puntatori a caratteri che contiene il menù delle pizze. Considerando che il codice è ancora da completare, vi posto quello che ho fatto fin'ora:

Server:
Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include <winsock.h>
  3. #include <string.h>
  4.  
  5. int main(int argc, char *argv[])
  6. {
  7.         SOCKET listenSocket;
  8.         SOCKET remoteSocket;
  9.         SOCKADDR_IN Server_addr;
  10.         SOCKADDR_IN Client_addr;
  11.        
  12.         int i, sin_size, scelta_effettuata;
  13.         short port;
  14.         int wsastartup;
  15.         int ls_result;
  16.        
  17.         char *pizze [] = {"01. Margherita \t\t\t3,10 Euro", "02. Olio e pomodoro \t\t2,80 Euro", "03. Ripieno  \t\t\t4,20 Euro",
  18.                 "04. Quattro stagioni \t\t4,50 Euro", "05. Capricciosa \t\t\t4,50 Euro", "06. Filetto di pomodoro  \t\t4,20 Euro"};
  19.        
  20.         char *bibite [] = {"01. Coca cola \t\t\t1,00 Euro", "02. Birra \t\t\t1,50 Euro", "03. Aranciata \t\t\t1,00 Euro",
  21.                 "04. Minerale \t\t\t0,50 Euro"};
  22.  
  23.  
  24. /* Inizializzazione della libreria Socket */
  25.         WORD wVersionRequested = MAKEWORD(2,2);
  26.         WSADATA wsaData;
  27.         wsastartup = WSAStartup(wVersionRequested, &wsaData);
  28.         if (wsastartup != NO_ERROR)
  29.                 printf("Errore WSAStartup()\n");
  30.  
  31.         /* Creazione della Socket che si porrà in ascolto di richieste del Client*/
  32.         listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  33.         if (listenSocket < 0)
  34.                 printf("Server: errore nella creazione della socket.\n");
  35.         else
  36.                 printf("La Listening Socket e' partita\n");
  37.  
  38.         /* Effettua la bind sull’indirizzo e porta ora specificati */
  39.         port = 4000;
  40.         Server_addr.sin_family = AF_INET;
  41.         Server_addr.sin_addr.s_addr = inet_addr ("127.0.0.1");
  42.         Server_addr.sin_port = htons(port);
  43.         if (bind(listenSocket,(SOCKADDR*)&Server_addr,sizeof(struct sockaddr_in)) < 0)
  44.                 printf("Server: errore durante la bind.\n");
  45.         /* La socket si pone in "ascolto" tramite la listen() */
  46.         ls_result = listen(listenSocket, SOMAXCONN);
  47.         if (ls_result < 0)
  48.                 printf("Server: errore durante la listen.\n");
  49.         else
  50.                 printf("La Socket e' in Ascolto\n");
  51.         /* La socket accetta la richiesta di connessione del Client */
  52.         sin_size = sizeof(struct sockaddr_in);
  53.         remoteSocket = accept(listenSocket, (struct sockaddr *)&Client_addr,&sin_size);
  54.         printf("Accettata Connessione con Client: %s\n",inet_ntoa(Client_addr.sin_addr));  
  55.         /* Il Server accetta il messaggio dal Client */
  56.        
  57.         recv(remoteSocket, (char *)&scelta_effettuata, sizeof(int), 0);
  58.         printf("Messaggio Arrivato: %d \n", scelta_effettuata);
  59.        
  60.         for (i=0; i<6; i++)
  61.         {
  62.                 send(remoteSocket,pizze[i], strlen(pizze[i]),0);
  63.                 printf ("Sto inviando: %s\n", pizze[i]);
  64.         }
  65.        
  66.        
  67.        
  68.         printf("Chiudo il Server\n");
  69.         close(remoteSocket);
  70.         WSACleanup();
  71.         return 0;
  72. }



Client:
Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include <winsock.h>
  3. #include <string.h>
  4.  
  5. int main()
  6. {
  7.                
  8.         int scelta, i;
  9.        
  10.         SOCKET clientsocket;
  11.         SOCKADDR_IN addr;
  12.         short port;
  13.         char pizze [100];
  14.         WORD wVersionRequested = MAKEWORD(2,2);
  15.         WSADATA wsaData;
  16.         WSAStartup(wVersionRequested, &wsaData);
  17.        
  18.        
  19.         printf ("\t\t\t* PIZZERIA BELLA NAPOLI *\n\t\t\t Viale Dei Giardini, 121\n\t\t\t     Tel. 081-102030\n\n\n\t\t\t    MENU' PRINCIPALE\n");
  20.         printf ("1. Visualizza menu' pizze\n2. Visualizza bibite\n3. Effettua ordinazione\n4. Esci\n\n");
  21.         printf ("Digita la tua scelta: ");
  22.         scanf ("%d", &scelta);
  23.         while ((scelta <1) || (scelta>4))
  24.         {
  25.                 scelta = 0;
  26.                 printf ("Hai digitato un valore non valido. Riprova.\n");
  27.                 printf ("Digita la tua scelta: ");
  28.                 scanf ("%d", &scelta);
  29.         }
  30.         if (scelta <4)
  31.         {
  32.                 port = 4000;  
  33.                 addr.sin_family = AF_INET;
  34.                 addr.sin_addr.s_addr = inet_addr("127.0.0.1");
  35.                 addr.sin_port = htons(port);
  36.                 clientsocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  37.                 if (connect(clientsocket, (LPSOCKADDR)&addr, sizeof(addr)) < 0)
  38.                         printf("Errore nella connessione con il Server");
  39.                 send(clientsocket,(char *)&scelta, sizeof(int),0);
  40.         //for (i=0; i<6; i++)
  41.         {
  42.                 recv (clientsocket, pizze, strlen(pizze),0);
  43.                 printf ("%s\n", pizze);
  44.         }
  45.                 //WSACleanup();   PERCHE'???
  46.  
  47.         }
  48.  
  49.         return 0;
  50.  
  51.         //system ("CLS");
  52.        
  53. }



In allegato, trovare uno screenshot dell'output generato dal programma.
Vi ringrazio in anticipo,

Antonio


MagoAntò ha allegato un file: output_reti.jpg (141274 bytes)
Clicca qui per guardare l'immagine

Ultima modifica effettuata da MagoAntò il 07/02/2009 alle 13:24
PM Quote
Avatar
theprogrammer (Normal User)
Guru^2


Messaggi: 2509
Iscritto: 28/01/2009

Segnala al moderatore
Postato alle 15:03
Sabato, 07/02/2009
Nel client, l'array di stringhe e' sbagliato. Deve essere, ad esempio

Codice sorgente - presumibilmente C/C++

  1. char pizze [6][80] = {"01. Margherita \t\t\t3,10 Euro", "02. Olio e pomodoro \t\t2,80 Euro", "03. Ripieno  \t\t\t4,20 Euro",
  2.         "04. Quattro stagioni \t\t4,50 Euro", "05. Capricciosa \t\t\t4,50 Euro", "06. Filetto di pomodoro  \t\t4,20 Euro"};



Nel server, la ricezione e' sbagliata ...


Codice sorgente - presumibilmente C/C++

  1. int p;
  2.  
  3. ...
  4.  
  5. for (i=0; i<6; i++)
  6. {
  7.     p = recv (clientsocket, pizze, 100, 0);
  8.     pizze[p]='\0';
  9.     printf ("%s\n", pizze);
  10. }


PM Quote
Avatar
MagoAntò (Normal User)
Rookie


Messaggi: 42
Iscritto: 07/02/2009

Segnala al moderatore
Postato alle 15:39
Sabato, 07/02/2009
Testo quotato

Postato originariamente da theprogrammer:

Nel client, l'array di stringhe e' sbagliato. Deve essere, ad esempio

Codice sorgente - presumibilmente C/C++

  1. char pizze [6][80] = {"01. Margherita \t\t\t3,10 Euro", "02. Olio e pomodoro \t\t2,80 Euro", "03. Ripieno  \t\t\t4,20 Euro",
  2.         "04. Quattro stagioni \t\t4,50 Euro", "05. Capricciosa \t\t\t4,50 Euro", "06. Filetto di pomodoro  \t\t4,20 Euro"};



Nel server, la ricezione e' sbagliata ...


Codice sorgente - presumibilmente C/C++

  1. int p;
  2.  
  3. ...
  4.  
  5. for (i=0; i<6; i++)
  6. {
  7.     p = recv (clientsocket, pizze, 100, 0);
  8.     pizze[p]='\0';
  9.     printf ("%s\n", pizze);
  10. }




Ok, adesso funziona :k:
Ci sono però delle cose che mi lasciano perplesso:

1. Alcune volte, se avvio prima il server e poi il client (cioè, la normalità), l'output generato è quello in figura 1, in allegato.

2. Alcune volte, se faccio partire prima il client e poi il server, l'output generato a schermo è quello di figura 2. Perchè la formattazione delle ultime due stringhe è sbagliata dal lato client mentre dal lato server viene visualizzata correttamente?

Dico "alcune volte" perchè ogni volta che avvio il programma, l'output è diverso; a volte esce come in figura 1, a volte come in figura 2 :( L'unica nota positiva è che non appaiono più quei caratteri "strani" di prima. Cosa sbaglio? Centrano le locazioni di memoria? :-|


MagoAntò ha allegato un file: output_bis.jpg (286719 bytes)
Clicca qui per guardare l'immagine

Ultima modifica effettuata da MagoAntò il 07/02/2009 alle 15:51
PM Quote
Avatar
theprogrammer (Normal User)
Guru^2


Messaggi: 2509
Iscritto: 28/01/2009

Segnala al moderatore
Postato alle 16:06
Sabato, 07/02/2009
Il problema e' che, se ancora non si molta esperienza con la programmazione, non si dovrebbe iniziare a scrivere programmi di una certa complessita' (come quelli client-server).

Anzi, prima bisognerebbe studiare i principi della comunicazione in rete (TCP) ...

La ricezione dei dati con i socket non avviene sempre cosi' come si trasmettono.

Per vari motivi, ogni recv non corrisponde ad ogni send. E' possibile che con una recv vengano ricevute due o piu' stringhe trasmesse con diverse send e questo e' normale nella comunicazione TCP.

Deve essere il programma che riceve a gestire la cosa e lo fa esaminando opportunamente i dati ricevuti (e questo implica un codice un po' piu' complesso di quello che hai scritto che e' evidentemente di tipo didattico).

Per rimediare ai piccoli problemi descritti, puoi modificare nel server, questa riga in questo modo

Codice sorgente - presumibilmente C/C++

  1. char pizze [6][50] = {"01. Margherita \t\t\t3,10 Euro\n", "02. Olio e pomodoro \t\t2,80 Euro\n", "03. Ripieno  \t\t\t4,20 Euro\n",
  2.         "04. Quattro stagioni \t\t4,50 Euro\n", "05. Capricciosa \t\t4,50 Euro\n", "06. Filetto di pomodoro  \t4,20 Euro\n"};



e dentro la for, questa riga cosi'

Codice sorgente - presumibilmente Plain Text

  1. printf ("%s", pizze[i]);



mentre nel client, la riga nel for deve essere

Codice sorgente - presumibilmente Plain Text

  1. printf ("%s", pizze);


    

PM Quote
Avatar
MagoAntò (Normal User)
Rookie


Messaggi: 42
Iscritto: 07/02/2009

Segnala al moderatore
Postato alle 16:45
Sabato, 07/02/2009
Testo quotato

Il problema e' che, se ancora non si molta esperienza con la programmazione, non si dovrebbe iniziare a scrivere programmi di una certa complessita' (come quelli client-server).



Hai ragione, purtroppo la questione è un po' difficile...8-|

In ogni caso, ho modificato ancora il codice come mi hai detto: problemi di formattazione non ce ne sono più e tutto funziona correttamente, solo che qualche volta capita che il client stampi a video più volte la stessa stringa. A questo punto, da come ho capito, dovrebbe dipendere dalla recv e dal funzionamento stesso di TCP/IP... :) Avete qualche altro consiglio da darmi?

Ultima modifica effettuata da MagoAntò il 07/02/2009 alle 17:44
PM Quote
Avatar
theprogrammer (Normal User)
Guru^2


Messaggi: 2509
Iscritto: 28/01/2009

Segnala al moderatore
Postato alle 20:01
Sabato, 07/02/2009
Non mi e' mai capitato, ma considera che quello che hai iniziato a scrivere e' solo lo "scheletro" di un server, in quanto si interrompe subito dopo la prima risposta (cosa che ovviamente ad un server non deve capitare ...).

Lo stesso dicasi per il server ...

Comunque, il consiglio e' di studiare bene i dettagli del TCP e della programmazione di rete e poi riprovare ...

PM Quote