Visualizzazione dei risultati da 1 a 6 su 6
  1. #1

    [c] da chat a battaglia navale.. per unix

    Ciao a tutti, partendo dal sorgente di una chat multiutente basata su select() sto cercando di modificarla per implementare poi un gioco tipo battaglia navale con un server che controlla più partite tra più client.. quello che non riesco a fare ora è a chiedere al cliente, appena collegato, di scegliere un nickname e salvarlo nell'apposito campo user[x].nick dove x è il numero dell'utente. Qualcuno saprebbe dirmi come fare? Sto provando in più modi, ma ogni volta c'è qualcosa che non va.. o non me lo salva.. o lo salva però se poi provo a stamparlo solo sul client che lo ha inserito, lo stampa su tutti i client.. allego il sorgente dell'intero server..

    Codice PHP:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <errno.h>

    #define SHOW 1      // command show
    #define MESSAGE 2
    #define HELP 3
    #define NICK 4
    #define NEWLINE 5



    void write_to_socket(int target,char *buff_to_send,int len);
    int check_for_command(char *buffer,int *p);
    int is_fd_valid(int destination) ;
    void type_writer(char *buf,int len,int fd);
    typedef struct
    {
      
    int id;  /* socket descripter */
      
    char nick[30]; /* store the nick here */
      
    short flag_nick;
    }
    USER;


    USER user[20];
    int usercount=0;

    int main(int argcchar *argv[])
    {
      
    fd_set master;   // master file descriptor list
      
    fd_set read_fds// temp file descriptor list for select()
      
    int PORT;                // porta sulla quale il server resta in ascolto
      
    struct sockaddr_in myaddr;     // server address
      
    struct sockaddr_in remoteaddr// client address
      
    int fdmax;        // maximum file descriptor number
      
    int listener;     // listening socket descriptor
      
    int newfd;        // newly accept()ed socket descriptor
      
    char buf[1024];    // buffer for client data
      
    int nbytes;
      
    int yes=1;        // for setsockopt() SO_REUSEADDR, below
      
    int addrlen;
      
    int ij,k,tmp,destination=0;
      
    int str_len;
      
    char c;
      
    char *tmp_ptr;
      
    //USER user[20];
      //int usercount=0;
      
    bzero(user,sizeof(USER));

      
    FD_ZERO(&master);    // clear the master and temp sets
      
    FD_ZERO(&read_fds);
      
      
      if (
    argc != 2) {
        
    fprintf(stderr"Sintassi: %s <porta>\n"argv[0]);
        exit(
    4);
      }

      
    PORT=atoi(argv[1]);

      
    // get the listener
      
    if ((listener socket(AF_INETSOCK_STREAM0)) == -1) {
        
    perror("socket error");
        exit(
    1);
      }

      
    // lose the pesky "address already in use" error message
      
    if (setsockopt(listenerSOL_SOCKETSO_REUSEADDR, &yes,
        
    sizeof(int)) == -1) {
        
    perror("setsockopt error");
        exit(
    1);
      }

      
    // bind
      
    myaddr.sin_family AF_INET;
      
    myaddr.sin_addr.s_addr INADDR_ANY;
      
    myaddr.sin_port htons(PORT);
      
    memset(&(myaddr.sin_zero), '\0'8);
      if (
    bind(listener, (struct sockaddr *)&myaddrsizeof(myaddr)) == -1) {
        
    perror("bind error");
        exit(
    1);
      }

      
    // listen
      
    if (listen(listener10) == -1) {
        
    perror("listen error");
        exit(
    1);
      }

      
    // add the listener to the master set
      
    FD_SET(listener, &master);

      
    // keep track of the biggest file descriptor
      
    fdmax listener// so far, it's this one

      // main loop
      
    for(;;) {
        
    read_fds master// copy it
        
    if (select(fdmax+1, &read_fdsNULLNULLNULL) == -1) {
          
    perror("select");
          exit(
    1);
        }

        
    // run through the existing connections looking for data to read
        
    for(0<= fdmaxi++) {
          if (
    FD_ISSET(i, &read_fds)) { // we got one!!
        
    if (== listener) {
          
    // handle new connections
          
    addrlen sizeof(remoteaddr);
          if ((
    newfd accept(listener, (struct sockaddr *)&remoteaddr,
              &
    addrlen)) == -1) { 
            
    perror("accept error");
          } else {
            
    FD_SET(newfd, &master); // add to master set
            
    if (newfd fdmax) {    // keep track of the maximum
              
    fdmax newfd;
            }
            
    user[usercount].id=newfd;
            ++
    usercount;
            
    printf(">> Accettata nuova connessione dal client %s sul socket %d\n"inet_ntoa(remoteaddr.sin_addr), newfd);
            
    bzero(buf,sizeof(buf));
            
    strcpy(buf,"\n\n\n\n\n\n\n\n\n\n\n********************************************************************************\n");
            
    str_len=strlen(buf);
            
    write_to_socket(newfd,buf,str_len);

            
            
    bzero(buf,sizeof(buf));
            
    strcpy(buf,"\n\t\t\t   ~~~~ BATTAGLIA NAVALE ~~~~\n\n");
            
    str_len=strlen(buf);
            
    type_writer(buf,str_len,newfd);
            
            
    user[1].flag_nick=1;
            
    strncpy(user[1].nick,"nick",30);

            
    bzero(buf,sizeof(buf));
            
    strcpy(buf,"********************************************************************************\n\n"
            "\t\t\t~Type /SHOW/ to list all online users\n\n"
            "\t~ To send a message to everyone in the room just type the message and press enter\n\n"
            "\t\t~ Type /numeric-user/ to send a message to particular user only\n\n"
            "\t\t ex: /6/ Hi number 6 how r u\n\n"
            "\t\t\t~ Type /HELP/ to see server commands\n\n"
            "********************************************************************************\n\n\n>>"
    );
                
    /* sprintf(buf,"Il nickname scelto e': ",user[1].nick);
            str_len=strlen(buf);
            write_to_socket(i,buf,str_len); */
            
            
    str_len=strlen(buf);
            
    write_to_socket(newfd,buf,str_len);
            
            
          }
        } else {
          
    // handle data from a client
          
    if ((nbytes recv(ibufsizeof(buf), 0)) <= 0) {
            
    // got error or connection closed by client
            
    if (nbytes == 0) {
              
    // connection closed
              
    printf(">> Socket %d chiuso. Il client %s si e' disconnesso.\n"iinet_ntoa(remoteaddr.sin_addr));
            } else {
              
    perror("recv");
            }
            
    close(i); // bye!
            
    FD_CLR(i, &master); // remove from master set
          
    } else {

            
    // we got some data from a client
            //printf("\n%s\n",buf);
            
    for(0<= fdmaxj++) {
              
    // send to everyone!
              
    if (FD_ISSET(j, &master)) {
            
    // except the listener and ourselves
            
    if (!= listener && != i) {
              switch(
    check_for_command(buf,&destination))
              {
                case 
    SHOW
                  
    //strcpy(buf,"Got the command request :-)\n>>\r\n" );
                  //str_len=strlen(buf);
                  
    kusercount-1;
                  
    bzero(buf,sizeof(buf));
                  while(
    k>=0)
                  {

                
    sprintf(buf,"<%d>\n>>",user[k].id);
                
    str_len=strlen(buf);
                
    write_to_socket(i,buf,str_len);
                --
    k;
                  }

                  
    j=1111// to end the loop
                  
    break;
                case 
    MESSAGE:
                  if( 
    is_fd_valid(destination) )
                  {
                
    tmp_ptr=buf;
                while(*
    tmp_ptr==' ')
                  ++
    tmp_ptr;
                
    c=destination;
                *(
    tmp_ptr+1)=i+'0';//(char)destination;
                
    tmp_ptr=strchr(buf,'\n');
                
    //str_len=strlen(buf);
                
    write_to_socket(destination,buf,tmp_ptr-buf+1);

                
    printf("\nGood show\n");
                  }
                  else
                  {
                
    bzero(buf,sizeof(buf));
                
    strcpy(buf,"Invalid user\n>>\r\n");
                
    str_len=strlen(buf);
                
    write_to_socket(i,buf,str_len);
                  }
                  
    j=1111// to end the loop
                  
    break;

                case 
    HELP:
                  
    bzero(buf,sizeof(buf));
                  
    strcpy(buf,"\n\n\n********************************************************************************\n\n\n"
                  "\t\t\t~Type /SHOW/ to list all online users\n\n"
                  "\t~ To send a message to everyone in the room \n"
                  "\t\t\tjust type the message and press enter\n\n"
                  "\t\t~ Type /numeric-user/ to send a message to particular user only\n\n"
                  "\t\t\t\t ex: /6/ Hi number 6 how r u\n\n"
                  "\t\t\t~ Type /HELP/ to see server commands\n\n\n>>"
                  "********************************************************************************\n\n\n\n>>" 
    );
                  
    str_len=strlen(buf);
                  
    write_to_socket(newfd,buf,str_len);

                    
    j=1111;
                break;
                case 
    NEWLINE:
                
    bzero(buf,sizeof(buf));
                
    sprintf(buf,">>");
                
    //str_len=strlen(buf);
                
    write_to_socket(i,buf,strlen(buf));
                
    j=1111;
                break;
                case 
    NICK:
                
    //printf("Got the nick\n");
                //bzero(buf,sizeof(buf));
                
    printf(buf);
                
    tmp_ptr=buf;
                
    tmp_ptr+=6;
                for(
    tmp=0;tmp<fdmax;++tmp)
                {
                  if(
    user[tmp].id==i)
                    break;
                }
                
    user[tmp].flag_nick=1;
                
    strncpy(user[tmp].nick,tmp_ptr,10);
                
    bzero(buf,sizeof(buf));
                
    sprintf(buf,"%s Joined the room\r\n",user[tmp].nick);
                
    str_len=strlen(buf);
                
    write_to_socket(j,buf,str_len);
                
    j=1111// to end the loop
                
    break;
                default:
                  
    write_to_socket(j,buf,nbytes);
                  break;
              }
            }
              }
            }
          }
        } 
          }
        }
      }

      return 
    0;
    }


    void write_to_socket(int target,char *buff_to_send,int len)
    {
      if( !
    write(target,buff_to_send,len) )
      {
        
    perror("Write");
        exit(
    0);
      }
    }

    int check_for_command(char *buffer,int *p)
    {
      
    char tmp[6];
      
    strncpy(tmp,buffer,5);
      while(*
    buffer==' ')
        ++
    buffer;
      if(!
    strncmp(buffer,"/SHOW/",6) || !strncmp(buffer,"/show/",6) )
        return 
    SHOW;
      else if(!
    strncmp(buffer,"/HELP/",6) || !strncmp(buffer,"/help/",6) )
        return 
    HELP;
      else if(!
    strncmp(buffer,"/NICK/",6) || !strncmp(buffer,"/NICK/",6) )
        return 
    NICK;

      else if((*
    buffer=='/') && (*(buffer+2)=='/'))
      {
        *
    p= *(buffer+1)-'0';
        return 
    MESSAGE;
      }
      else if( *
    buffer=='\r')
        return 
    NEWLINE;

      else
        return 
    0;


    }

    int is_fd_valid(int destination)
    {
      
    int i;
      for(
    i=0;i<usercount;++i)
        if( 
    user[i].id==destination)
          return 
    1;
      return 
    0;
    }

    void type_writer(char *buf,int lenint fd)
    {
      
    int i=0;
      for(
    i=0;i<len;++i)
      {
        
    write_to_socket(fd,buf+i,sizeof(char));
        
    usleep(50000);
      } 


  2. #2

  3. #3
    Non mi serve a scriverlo ex-novo perchè tutte, e dico tutte, le cose presenti nel server che ho postato mi servono.. devo modificare solo un pò il menù ed i possibili comandi accettati.. un paio di funzioni che non mi servivano le ho eliminate.. tutto il resto mi serve.. il problema ora è aggiungere a quello che ho.. ho già scritto qualche altro pezzo di codice per disegnare il campo di battaglia e posizionare le navi, ma ho bisogno di capire bene come stampare cosa e dove.. e quindi torno al problema di cui su.. se mi fate vedere come inserire il nickname e magari stampare all'interno del client che ha inserito il nickname la frase "Il nickname scelto è: %nick" posso modificare anche la funzione per il disegno del campo di battaglia e fare in modo che venga stampata correttamente e andare avanti..

  4. #4
    volendolo scrivere daccapo.. questo è il server:

    Codice PHP:
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>

    /* -------------------- main() -------------------- */

    main (int argcchar *argv[])
    {
      
    int portsockfdclient_lenvaluex;
      
    struct sockaddr_in serverclient;

     if (
    argc != 2) {
       
    fprintf(stderr"Sintassi: %s <porta>\n"argv[0]);
       exit(
    4);
     }
      
    port atoi(argv[1]);

      
    setbuf(stdout,NULL);                    /* serve per settare a unbuffered stdout */

      /* creo l'oggetto socket
         tecnicamente "sock" viene chiamato rendevous descriptor */
      
    sock socket(AF_INETSOCK_STREAM0);         /* SOCK_STREAM per TCP
                                        SOCK_DGRAM per UDP */
      
    if (sock 0) {
        
    perror("Errore -> stream socket");
        exit(
    1);
      }

      
    /* creo l'oggetto "indirizzo del server" */
      
    server.sin_family AF_INET;                 /* per internet domain; AF_UNIX x unix pipes */
      
    server.sin_addr.s_addr htonl(INADDR_ANY);         /* il kernel e' libero di scegliere
                                    su quale interfaccia di rete creare
                                    il socket */
      /* nota il host to network translation */
      
    server.sin_port htons(port);

      
    /* quanto segue serve per per poter riusare piu' volte lo stesso indirizzo
         (cioe' per piu' server lanciati successivamente) */
      
    value 1;
      if (
    setsockopt(sockSOL_SOCKETSO_REUSEADDR, (char *)&valuesizeof(value)) < 0) {
        
    perror("Errore -> setsockopt");
        exit(
    5);
      }

      
    /* sockaddr e' un supertipo di sockaddr_in, che include anche sockaddr_un */
      
    if (bind(sock, (struct sockaddr *) &serversizeof(server)) < 0) {
        
    perror("Errore -> binding socket");
          exit(
    2); 
      }

      
    listen(sock,2);                     /* 2 = lunghezza max della coda attesa */
      
      // signal(SIGCHLD,SIG_IGN);                /* questa chiamata serve per evitare che il figlio */
                                /* rimanga 'zombie' solo perche' deve restituire il
                                      codice di ritorno al padre */

      
    while (1) {  
        
    client_len sizeof(client);
        
    printf("\nServer in attesa\n");
        if ((
    fd accept(sock, (struct sockaddr *) &client, &client_len)) < 0) {
          
    perror("Errore -> accept socket");            /* fd e' un connection descriptor */
          
    exit(3);
        }
        if (
    fork()==0){                    /* figlio */
          /* guardiamo i dati del client */
          
    printf("Accettata nuova connessione dal client: IP=%s, sul socket %d\n",
             
    inet_ntoa(client.sin_addr),fd);
          exit(
    0);                        /* figlio termina */
        
    } else {
          
    close(fd);                    /* padre chiude sempre fd */
        
    }
      }

    e questo è il client:

    Codice PHP:
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>


    /* -------------------- main() -------------------- */

    main (int argcchar *argv[])
    {
      
    struct hostent host_info;
      
    struct sockaddr_in server;
      
    int sockport;
      
    char *server_name;

      if ((
    argc 3) || (argc 2)) {
        
    fprintf(stderr"Sintassi: %s [host] porta\n"argv[0]);
        exit(
    1);
      }
      
    server_name = (argc==3) ? argv[1] : "localhost" ;
      
    port atoi(argv[2]);
      
    printf("Provo la connessione con: %s\n",server_name);

      
    /* creo l'oggetto socket */
      
    sock socket(AF_INETSOCK_STREAM0); 
      if (
    sock 0) {
        
    perror("Errore-> stream socket");
        exit(
    1);
      }

      
    /* creo l'indirizzo del server */
      
    host_info gethostbyname(server_name);
      if (
    gethostbyname(server_name) == NULL) {
        
    // herror("in gethostbyname");
        
    fprintf(stderr"Host sconosciuto: %s\nRiprova utilizzando l'indirizzo ip del server.\n"server_name);
        exit(
    1);
        
    /*server.sin_family = AF_INET;         
        if (inet_aton(server_name, &(server.sin_addr))==0){
          herror("nella conversione dell'indirizzo IP");
          exit(1);
        }
        memset(&(server.sin_zero), '\0', 8); // zero the rest of the struct */
      
    } else {            /* estrai i dati da host_info */
        
    server.sin_family host_info->h_addrtype;
        
    memcpy((char *)&server.sin_addr,
           
    host_info->h_addr,
           
    host_info->h_length);
      }
      
    server.sin_port htons(port);

      
    /* eseguo la connessione */
      
    if (connect(sock, (struct sockaddr *)&serversizeof server) < 0) {
        
    perror("Errore -> connect server");
        exit(
    1);
      }

      
    /* ora siamo collegati*/
      
    printf("Connesso al server: %s\n",server_name);

    ora come procedo per far si che venga richiesto ad ogni client di inserire un nickname, che i nickname dei vari client vengano inseriti in una lista, mostrata ad ogni client quando si collega, così da dare ad ogni client la possibilità di scegliere a quale client collegarsi per iniziare una partitia..

  5. #5

    Re: [c] da chat a battaglia navale.. per unix

    Originariamente inviato da trafalguar

    Codice PHP:
              }
            }
              }
            }
          }
        } 
          }
        }
      } 
    stupendo ;-) Ma sarebbe meglio evitare certi livelli d'annidamento.

  6. #6
    mmm.. già.. ma comunque non si và avanti

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.