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++ - Problema con server multiprocesso in C
Forum - C/C++ - Problema con server multiprocesso in C

Avatar
trenta3 (Normal User)
Newbie


Messaggi: 16
Iscritto: 17/12/2008

Segnala al moderatore
Postato alle 21:32
Mercoledì, 17/12/2008
Premetto che sono da poco entrato nelmondo della programmazione.
Avrei un problema:
Ho il codice di un banale server e di un banale client che si scambiano messaggi tra loro.
Il problema sorge quando vorrei fare in modo che il server supporti la connessioni anche di più client contemporaneamente come in una chat.
Ho cercato su internet ed ho scoperto che servirebbe un programma multiprocesso ma non riesco a capire come fare:
Il mio compilatore, Dev-c++, mi da errore quando metto il comando fork().

Grazie in anticipo a chi risponderà.(Mi basterebbe una guida ,possibilmente in Italiano ma va bene anche in Francese e in Inglese, che spieghi per bene il fork e i programmi multiprocesso.)
Metto per comodità i codici(senza fork):

Server.c

Codice sorgente - presumibilmente C/C++

  1. /****************************
  2. Sorgenti della guida
  3. www.fabrixosft.altervista.org
  4. www.pierotofy.it
  5. ***************************/
  6.  
  7. #include <stdio.h>
  8. #include <winsock.h>
  9. main(){
  10.      
  11. //INIZIALIZZAZIONE WINSOCK
  12. WSADATA wsadata;
  13. int Versione= WSAStartup(MAKEWORD(2,2),&wsadata);
  14. //Gestione dell'errore
  15. if(Versione!=NO_ERROR){ //o anche if(Versione != 0){
  16. printf("Errore nell'inizializzazione delle socket");
  17. }
  18. //***************************************
  19.  
  20.  
  21.  
  22. //DICHIARAZIONE E CREAZIONE DELLA SOCKET
  23. //Dichiariamo la SOCKET che verrà chiamata server
  24. SOCKET server;
  25. //Associamo alla socket "AF_INET", ovvero internet adress family (il più usato), "SOCK_STREAM", per far girare la socket sul protocollo TCP(esiste anche il tipo "SOCK_DGRAM" per usare la socket su un protocollo UDP),IPPROTO_TCP , ovvero la socket userà il protocollo TCP
  26. server=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  27. //gestione dell'errore
  28. if(server==INVALID_SOCKET){
  29. printf("Errore: Socket non valida");
  30. //Liberiamo le risorse della socket
  31. WSACleanup();
  32. }//*************************************
  33.  
  34. //STRUTTURA SOCKADDR_IN E ASSEGNAZIONE DI PARAMETRI AL SERVER
  35. SOCKADDR_IN  parametri_server;
  36. //Come detto prima passiamo la internet address family
  37. parametri_server.sin_family=AF_INET;
  38. //ora diciamo su che indirizzo IP il server deve attivarsi, in questo caso 127.0.0.1 ovvero l'host locale
  39. parametri_server.sin_addr.s_addr = INADDR_ANY; //In questo modo faremo collegare da remoto il clien altrimenti mettere "inet_addr("127.0.0.1");"
  40. //Ora passiamo al server la porta di connessione, in questo caso la 1000
  41. parametri_server.sin_port=htons(1000);
  42. //************************************************************
  43.  
  44. //FUNZIONE BIND
  45. int funzione_bind;
  46. funzione_bind=bind( server, (SOCKADDR*) ¶metri_server, sizeof(parametri_server));
  47. if(funzione_bind ==SOCKET_ERROR ){
  48. /*if(bind!=0){
  49. printf("Funzione bind non riuscita\\n");*/
  50. //Chiudiamo correttamente la socket
  51. printf("Errore\n");
  52. closesocket(server);
  53. WSACleanup();
  54. }
  55. //****************************************************
  56.  
  57.  
  58. //FUNZIONE LISTEN(); RIMANE IN ASCOLTO
  59. int funzione_listen;
  60. funzione_listen=listen(server,1);
  61. if(funzione_listen ==SOCKET_ERROR)
  62. //Gestione dell'errore
  63. printf("Errore nella funzione listen \n");
  64. //************************************
  65.  
  66.  
  67. //FUNZIONE ACCEPT(); ACCETTA LA CONNESSIONE
  68. //Creiamo un elemento di tipo SOCKET
  69. SOCKET Accetta_connessioni;
  70. //ciclo infinito che attende la connessione
  71. printf("Attendo la connesione d un client\n");
  72. while(1){
  73. //dichiariamo la SOCKET Accetta_connessioni come errore ...
  74. Accetta_connessioni=ERROR;
  75. //in modo da innestare un altro ciclo while che si interrompe solo quando la SOCKET Accetta_connessioni non è più  ERROR, ovvero finchè non avviene la connessione con un client.
  76. while(Accetta_connessioni==ERROR){
  77. //La struttura della accept deve prendere 3 parametri, l primo obbligatorio e gli altri opzionali, a noi interessa solo il primo parametro(ovvero SOCKET server) e in questa guida non spiegherò a cosa servono gli altri 2 che setteremo a NULL
  78. Accetta_connessioni=accept(server,NULL,NULL);
  79. }
  80. //Se il ciclo si interrompe significa che un client si è connesso
  81. printf("Un client ha effettuato una connessione!");
  82. //Assegnamo alla SOCKET server la socket Accetta_connessioni.
  83. server=Accetta_connessioni;
  84. //con un break; usciamo dal ciclo infinito
  85. break;
  86. }
  87. //********************************
  88.  
  89.  
  90. //FUNZIONE RECV PER LA RICEZIONE DEI DATI
  91. //Dichiariamo il buffer contenente i dati ricevuti
  92. int ricevuto;
  93. char ricezione_dati[100];
  94. do{
  95. //Funzione recv per ricevere i dati
  96. recv(server,ricezione_dati,100,0);
  97. //Outputiamo i dati ricevuti
  98. printf("\nHo ricevuto >>> %s ",ricezione_dati);
  99. //Il ciclo continua finchè non viene digitato "Chiuditi"
  100. }while(strcmp(ricezione_dati,"Chiuditi")!=0);
  101. getchar();
  102. //*************************************
  103.  
  104. }



Client.c

Codice sorgente - presumibilmente C++

  1. /****************
  2. Sorgenti della guida
  3. www.fabrixsoft.altervista.org
  4. www.pierotofy.it
  5. ****************/
  6. #include <stdio.h>
  7. #include <winsock.h>
  8.  
  9. char IP[20];
  10.  
  11. main(){
  12. //Richiediamo all'utente l'IP e lo memorizziamo
  13. printf("Digita l'IP di connessione >>>");
  14. scanf("%s",IP);
  15.  
  16. //Inizializziamo il Winsock
  17. WSADATA wsadata;
  18. int Valore;
  19. Valore = WSAStartup( MAKEWORD(2,2), &wsadata );
  20. if ( Valore != NO_ERROR )
  21. printf("Errore nell'inizializzazione\\n");
  22. //************************
  23.  
  24. //Creiamo la socket
  25. SOCKET client;
  26. client= socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
  27. //Gestione dell'errore
  28. if ( client== INVALID_SOCKET ) {
  29. printf("Errore nella creazione della socket\\n");
  30. //Liberiamo le risorse del winsock
  31. WSACleanup();
  32. }
  33. //****************************    
  34.    
  35.    
  36. //ASSEGNAMO DEI PARAMETRI AL CLIENT
  37. SOCKADDR_IN parametri_client;
  38. //internet adress family
  39. parametri_client.sin_family = AF_INET;
  40. //Mettiamo come IP di connessione quello immesso dall' utente
  41. parametri_client.sin_addr.s_addr = inet_addr( IP );
  42. //porta numero 1000
  43. parametri_client.sin_port = htons( 1000);
  44. //**********************************
  45.  
  46. //FUNZIONE CONNECT();
  47. //Dichiaro una variabile int connessione
  48. int connessione;
  49. //assegno a connessione la funzione connect();
  50. connessione=connect(client,(SOCKADDR*) ¶metri_client,sizeof(parametri_client));
  51. //Gestione dell'errore
  52. if( connessione == SOCKET_ERROR){
  53. printf("Connessione fallita \\n");
  54. //Chiudo la scoket
  55. closesocket(client);
  56. WSACleanup();
  57. }
  58. //*****************************
  59.  
  60.  
  61. //Dichiaro un buffer dove salverò il messaggio che verrà digitato dall'utente
  62. char invio_dati[100];
  63. do{
  64. printf("Digita il messaggio da inviare al server >>> ");
  65. //Prendo il messaggio
  66. fflush(stdin);
  67. _sleep(100);
  68. gets(invio_dati);
  69. //Invio il messaggio
  70. send(client,invio_dati,100,0);
  71. //Il ciclo si ripete finche non viene digitato "Chiuditi"
  72. }while(strcmp(invio_dati,"Chiuditi")!=0);
  73. //Aspetto la pressionde di un tasto e chiudo il programma
  74. getchar();
  75. return 0;
  76. }


Ultima modifica effettuata da trenta3 il 17/12/2008 alle 21:34
PM Quote
Avatar
mc (Normal User)
Rookie


Messaggi: 52
Iscritto: 04/12/2008

Segnala al moderatore
Postato alle 2:24
Giovedì, 18/12/2008
La fork non esiste in windows.
Oltretutto ti consiglio qualcosa di meglio di DevC++, magari Code::Block.
Secondo il tuo codice è tutto appicicato, oltretutto tra commenti, e ci sono degli errori.
Il primo che ho visto è che scrivi main, al posto di int main(void).
Poi per gli altri errori vedremo quando avrai reso il codice più leggibile.
Grazie.
:-|

PM Quote
Avatar
eddiewrc (Member)
Expert


Messaggi: 560
Iscritto: 30/04/2006

Segnala al moderatore
Postato alle 12:37
Giovedì, 18/12/2008
@Code::Block (si scrive così?) gira su linux?

@33: windows non supporta la programmazione multiprocesso, e soprettutto fork(), exec..() e tutte le altre sono system call specifiche dei sistemi unix, quindi non è il compilatore che è marcio, semplicemente win non possiede quelle sys call.

ti basta passare a linux o scaricare una virtual machine (quella della sun è free) e installarci qualche distro del pinguino, così puoi rimanere in win e programmare cmq processi concorrenti!

ah dimenticavo... ovviamente in linux il codice per utilizzare le socket è diverso.. infatti in questo programma usi delle api di win, mentre col pinguino devi usare le sue system call.

ciao


Ultima modifica effettuata da eddiewrc il 18/12/2008 alle 12:39
PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6230
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 14:22
Giovedì, 18/12/2008
Windows non supporta le fork, come ti hanno giustamente detto, ma puoi ottenere il risultato desiderato utilizzando i threads. Dai uno sguardo sull'MSDN per le relative API.


Il mio blog: https://piero.dev
PM Quote
Avatar
Bond93 (Ex-Member)
Pro


Messaggi: 135
Iscritto: 04/05/2008

Segnala al moderatore
Postato alle 15:13
Giovedì, 18/12/2008
Si si scrive Code::Block ( XD molto C++ XD ) gira fantasticamente su linux supporta già di default le maggiri librerie grafiche ( SDL OGL GTK+ <ecc )
Te lo consiglio veramente è ottimo!!

PM Quote
Avatar
eddiewrc (Member)
Expert


Messaggi: 560
Iscritto: 30/04/2006

Segnala al moderatore
Postato alle 15:22
Giovedì, 18/12/2008
non vorrei andare OT ma grazie, lo guarderò! devo fare un progettone e nn riesco a trovare un ide nn complichi le cose + di quel che le ha complicate il prof..;)

PM Quote
Avatar
trenta3 (Normal User)
Newbie


Messaggi: 16
Iscritto: 17/12/2008

Segnala al moderatore
Postato alle 16:13
Giovedì, 18/12/2008
Grazie per tutte le risposte.
Ho capito che mi devo rassegnare, vedo su MSDN per le API su Windows.

Il codice è stato preso da una guida alla programmazione client server su questo sito e ho appiccicato quella perchè quella con fork aveva una confusione tale che non riuscivo a capire quali parti togliere e quindi l' ho buttata via.
Fortuna che fork() su win non si può usare alrimenti starei a rodermi il fegato XD

Grazie ancora per le risposte, mi faccio risentire quando ho letto MSDN.

PM Quote
Avatar
trenta3 (Normal User)
Newbie


Messaggi: 16
Iscritto: 17/12/2008

Segnala al moderatore
Postato alle 17:04
Sabato, 20/12/2008
Vi volevo segnalare che ho trovato un ottimo tutorial sui thread <questo> e ho fatto questo programma come server:

Il problema è che, nel thread chiamato thread1 quando c'è il comando recv il programma non riconosce server(1° parametro) perchè sta nell'altra funzione(main), come posso fare?
Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include <winsock.h>
  3. #include <windows.h>
  4.  
  5. long WINAPI Thread1(LPWORD ret);
  6.  
  7. int cl= 100;
  8.  
  9. int main (){
  10.     HANDLE hThread[1];
  11.     DWORD dwID[1];
  12.     int count=0;
  13.     int d;
  14.    
  15.      
  16.      WSADATA wsadata;
  17.      int Versione= WSAStartup(MAKEWORD(2,2),&wsadata);
  18.      
  19.      if(Versione!=NO_ERROR){
  20.      printf("Errore nell'inizializzazione delle socket\n");
  21.      return 1;
  22.      }
  23.  
  24.  
  25.  
  26.      
  27.      SOCKET server;
  28.    
  29.      server=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  30.    
  31.      if(server==INVALID_SOCKET){
  32.      printf("Errore: Socket non valida\n");
  33.      return 1;
  34.      }
  35.  
  36.      SOCKADDR_IN  parametri_server;
  37.    
  38.      parametri_server.sin_family=AF_INET;
  39.    
  40.      parametri_server.sin_addr.s_addr = INADDR_ANY;
  41.    
  42.      parametri_server.sin_port=htons(1000);
  43.  
  44.      int funzione_bind;
  45.      funzione_bind=bind( server, (SOCKADDR*) &parametri_server, sizeof(parametri_server));
  46.       if(funzione_bind ==SOCKET_ERROR ){
  47.       printf("Funzione bind non riuscita\n");
  48.  
  49.       closesocket(server);
  50.       WSACleanup();
  51.       return 1;
  52.       }
  53.      
  54.      int funzione_listen;
  55.      funzione_listen=listen(server,1);
  56.      if(funzione_listen ==SOCKET_ERROR){
  57.  
  58.      printf("Errore nella funzione listen \n");
  59.      closesocket(server);
  60.      WSACleanup();
  61.      return 1;
  62.      }
  63.  
  64.      SOCKET Accetta_connessioni;
  65.    
  66.      printf("Attendo la connesione di un client\n");
  67.      while(1){
  68.    
  69.      Accetta_connessioni=ERROR;
  70.      
  71.      while(Accetta_connessioni==ERROR){
  72.      
  73.      Accetta_connessioni=accept(server,NULL,NULL);
  74.      }
  75.    
  76.      printf("Un client ha effettuato una connessione!\n");
  77.       count ++;
  78.       cl ++;
  79.       printf("N. client: %d\n", cl);
  80.       printf("Client connessi: %d\n\n", count);
  81.     hThread[0] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Thread1,NULL,0,&dwID[0]);
  82.      
  83.      }
  84.  
  85. }  
  86.      
  87.  
  88.    
  89.    
  90.    
  91.    long WINAPI Thread1(LPWORD ret)
  92. {
  93.     int ricevuto;
  94.      char ricezione_dati[256];
  95.      do{
  96.    
  97.      recv(server,ricezione_dati,256,0);
  98.      printf("\nHo ricevuto dal client%d>>> %s ",cl,ricezione_dati);
  99.  
  100.      }
  101.      while(strcmp(ricezione_dati,"Chiuditi")!=0);
  102.      getchar();
  103.    
  104.      closesocket(server);
  105.      WSACleanup();
  106.      return 0;
  107.    
  108. }


PM Quote