Distanza di Hamming di due caratteri

di il
2 risposte

Distanza di Hamming di due caratteri

Questo è il mio progetto:
Si progetti e si implementi in linguaggio C un’applicazione Client/Server in cui Il Client invia due caratteri ed il Server restituisce la distanza di hamming della rappresentazione binaria dei due caratteri secondo i codice ascii.
Si ricorda che la distanza di Hamming tra due stringhe di ugual lunghezza è il numero di posizioni nelle quali i simboli corrispondenti sono diversi.

Ad esempio dati x=’b’ e y=’g’, la codifica ascii del carattere ‘b’ in decimale è 98 in binario 01100010, la codifica ascii del carattere ‘g’ in decimale è 103 in binario 01100111.
La distanza di Hamming tra 01100010 e 01100111 è 2.

Si implementi un Server concorrente (tramite thread o fork) ed un client che possa essere interrotto o stoppato solo dopo avere ricevuto la risposta dal server o solo dopo un timeout di 2 minuti.

La comunicazione tra Client e Server segue il protocollo seguente:
1. Il Client legge da linea di comando l’indirizzo, il numero di porta del server e si collega al Server.
2. Il Server invia al Client la stringa “OK”
3. Il Client dopo la lettura di OK, invia i  due caratteri
4. Il Server invia al Client la stringa “OC” calcola la distanza e la invia al Client, se i caratteri sono entrambi ‘0’, chiude la connessione, viceversa invia OK
5. Il Client dopo la lettura di OC attende il risultato e se ha inviato due ‘0’ termina , viceversa va al passo 3

Ho scritto in C il procedimento standard per calcolare la distanza di Hamming:
#include <stdio.h>
#include <stdlib.h>

int main (void) 
{
	int x, y, h;                              //getchar restiruisce interi ..... h = distanza di Hamming
	
	printf("Introduci due caratteri consecutivamente:   ");
	
	x = getchar(); 
	y = getchar();
	
	//Creazione di due vettori di dimensione 8 bit
	int vx[8] = {0}, vy[8] = {0};
	
	//Conversione da decimale a binario del primo carattere
	int i = 0;  
	int t = x;                     //indice del vettore
	while (t > 0) {
	  vx[i++] = t % 2;
	  t /= 2;                       // t = t / 2;	
	}
	//Conversione da decimale a binario del secondo carattere
	t = y;
	i = 0;
	while (t > 0) {
	  vy[i++] = t % 2;
	  t /= 2;                       // t = t / 2;	
	}
	//Stampa il primo carattare convertito in binario
	printf("\nIl carattere %c in decimale: %d, in binario corrisponde: \n", x, x);
	for (i=7; i>=0; i--)
	  printf ("%d", vx[i]);
	
	//Stampa il secondo carattare convertito in binario 
	printf("\nIl carattere %c in decimale: %d, in binario corrisponde: \n", y, y);
	for (i=7; i>=0; i--)
	  printf ("%d", vy[i]);
	  
	//Distanza di Hamming
	h = 0;                        //contatore della distanza
	for (i = 0; i < 8; i++)
	  if (vx[i] != vy[i])
	    h++;	  	  
	
	//Stampa la distanza di Hamming
	printf ("\nLa distanza di Hamming tra %c e %c e' : %d ", x, y, h); 
printf("\n\n\n"); 	  
return 0;
}
Non ho ben capito se devo farlo col protocollo TCP o UDP.
Se voglio usare il protocollo UDP, i due codici standard Client e Server sono questi:

SERVER UDP
#include <stdio.h>
#include <stdlib.h> 
#include <string.h> /* memset() */ 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <netdb.h> 
#include <unistd.h> /* close() */ 
#define LOCAL_SERVER_PORT 4000 
#define MAX_MSG 100 
int main(int argc, char *argv[]) 
{int sd, rc, n, cliLen; 
 struct sockaddr_in cliAddr, servAddr; 
 char msg[MAX_MSG]; 
 /* socket creation */ 
 sd=socket(AF_INET, SOCK_DGRAM, 0); 
 if(sd<0) 
  {printf("%s: cannot open socket \n",argv[0]); 
   exit(1); 
  } 
 /* bind local server port */ 
 servAddr.sin_family = AF_INET; 
 servAddr.sin_addr.s_addr = htonl(INADDR_ANY); 
 servAddr.sin_port = htons(LOCAL_SERVER_PORT); 
 rc = bind (sd, (struct sockaddr *) &servAddr,sizeof(servAddr)); 
 if(rc<0)
  {printf("%s: cannot bind port number %d \n",  argv[0], LOCAL_SERVER_PORT); 
   exit(1); 
  } 
 printf("%s: waiting for data on port UDP %u\n", argv[0],LOCAL_SERVER_PORT); 
 /* server infinite loop */ 
 while(1) 
  {/* init buffer */ 
   memset(msg,0x0,MAX_MSG); 
   /* receive message */ 
   cliLen = sizeof(cliAddr); 
   n = recvfrom(sd, msg, MAX_MSG, 0, (struct sockaddr *) &cliAddr, &cliLen); 
   if(n<0) 
   {printf("%s: cannot receive data \n",argv[0]);continue;} 
    /* print received message */ 
    printf("%s: from %s:UDP%u : %s \n", 
    argv[0],inet_ntoa(cliAddr.sin_addr), 
    ntohs(cliAddr.sin_port),msg); 
   }  /* end of server infinite loop */ 
 return 0; 
} 
CLIENT UDP
#include <stdio.h>
#include <stdlib.h> 
#include <string.h> /* memset() */ 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <netdb.h> 
#include <unistd.h> 
#include <sys/time.h> /* select() */ 
#define REMOTE_SERVER_PORT 4000
#define MAX_MSG 100 

int main(int argc, char *argv[]) 
{int sd, rc, i; 
 struct sockaddr_in cliAddr, remoteServAddr; 
 struct hostent *h; 
 /* check command line args */ 
 if(argc<3) 
 {printf("usage : %s <server> <data1> ... <dataN> \n", argv[0]);
  exit(1);
 } 
 /* get server IP address (no check if input is IP address or DNS name */ 
 h = gethostbyname(argv[1]); 
 if(h==NULL) 
 {printf("%s: unknown host '%s' \n", argv[0], argv[1]); 
  exit(1); 
 } 
 printf("%s: sending data to '%s' (IP : %s) \n", argv[0], h->h_name, 
 inet_ntoa(*(struct in_addr *)h->h_addr_list[0])); 
 remoteServAddr.sin_family = h->h_addrtype; 
 memcpy((char *) &remoteServAddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length); 
 remoteServAddr.sin_port = htons(REMOTE_SERVER_PORT); 
 /* socket creation */ 
 sd = socket(AF_INET,SOCK_DGRAM,0); 
 if(sd<0)
 {printf("%s: cannot open socket \n",argv[0]); 
  exit(1); 
 } 
 /* bind any port */ 
 cliAddr.sin_family = AF_INET; 
 cliAddr.sin_addr.s_addr = htonl(INADDR_ANY); 
 cliAddr.sin_port = htons(0); 
 rc = bind(sd, (struct sockaddr *) &cliAddr, sizeof(cliAddr)); 
 if(rc<0)
 {printf("%s: cannot bind port\n", argv[0]); 
  exit(1); 
 } 
 /* send data */ 
 for(i=2;i<argc;i++)
 {rc = sendto(sd, argv[i], strlen(argv[i])+1, 0,(struct sockaddr *) &remoteServAddr,sizeof(remoteServAddr)); 
  if(rc<0)
  {printf("%s: cannot send data %d \n",argv[0],i-1); 
   close(sd); 
   exit(1); 
  } 
 } 
return 0; 
}
Come faccio a unire il codice C con Client/Server e implementare un server concorrente tramite thread o fork?

2 Risposte

  • Re: Distanza di Hamming di due caratteri

    Intanto fai una cosa piu' semplice (per modo di dire)
    - implementa l'architettura client/server.

    l'architettura deve prevedere:
    1) il client si connette e si disconnette al server
    2) il client invia un messaggio al server ed il server risponde con un messaggio

    Qui, messaggio e' semplicemente una sequenza di byte della quale DEVI conoscere la lunghezza (quando la invii e quando la ricevi, quindi NON NECESSARIAMENTE la stessa)

    Per farlo e' semplice: STUDIATI la docmentazione relativa alle librerie in C/C++ per realizzare connessioni mediante il protocollo TCP/IP.

    Ad esempio: http://cpp-netlib.org, https://curl.haxx.se/libcurl

    ma con un po' di pazienza puoi trovare anche altro

    https://stackoverflow.com/questions/118945/best-c-c-network-library
  • Re: Distanza di Hamming di due caratteri

    Ho scritto così il codice :
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <strings.h>
    #include <time.h>
    #include <pthread.h>
    #include <unistd.h>
    #include <sys/types.h> // system defined identifiers.
    #include <netinet/in.h> // internet address structure.
    #include <sys/socket.h> // Need 4 socket(), bind(),
    #include <netdb.h>
    
    #define BUF_SIZE            1024    // buffer size in bytes
    #define PORT_NUM            6110    // Port number for a Web server (TCP 5080)
    #define TRUE                  1
    #define FALSE                 0
    #define COUNTDOWN             120
    
    void clean_stdin(void)
    {
        int c;
        do
        {
            c = getchar();
        }
        while (c != '\n' && c != EOF);
    }
    
    
    int readLine(int fd, char data[])
    {
       size_t len = 0;
       while (len < BUF_SIZE)
       {
          char c;
          int ret = read(fd, &c, 1);
          if (ret < 0)
          {
              data[len] = 0;
              return len; // EOF reached
          }
          if (c == '\n')
          {
              data[len] = 0;
              return len; // EOF reached
          }
          data[len++] = c;
       }
    }
    
    void* threadFunction(void* args)
    {
        time_t seconds = *(time_t*) args;
        time_t endwait;
        time_t start = time(NULL);
        
    
        endwait = start + seconds;
    
        printf("start time is : %s", ctime(&start));
    
        while (start < endwait)
        {
            sleep(1);   // sleep 1s.
            start = time(NULL);
        }
    
        printf("end time is %s", ctime(&endwait));
    
        exit(10);
    }
    
    int main(void)
    {
        int                 clientSocket;
        struct sockaddr_in  serverAddress;
        char                in_buf[BUF_SIZE], out_buf[BUF_SIZE];
        struct hostent      *h;
        pthread_t           thread;
        time_t seconds = COUNTDOWN;
        
        serverAddress.sin_family = AF_INET;
        serverAddress.sin_port = htons(PORT_NUM);
        h=gethostbyname("localhost");
        if (h==0)
        {
            printf("Gethostbyname fallito\n");
            exit(1);
        }
        
        bcopy(h->h_addr,&serverAddress.sin_addr,h->h_length);
        clientSocket = socket(AF_INET , SOCK_STREAM , IPPROTO_TCP);
        if (clientSocket == -1)
        {
            printf("Could not create socket");
        }
        puts("Socket created");
         
        if(connect(clientSocket , (struct sockaddr *)&serverAddress , sizeof(serverAddress)) < 0)
        {
            perror("connect failed. Error");
            exit(1);
        }     
        puts("Connected\n");
        
        pthread_create(&thread, NULL, threadFunction, &seconds);
        
        while(strcmp(in_buf, "OK") != 0)
        {
            sleep(1);
            recv(clientSocket , in_buf, BUF_SIZE, 0);
        }
        
        puts(in_buf);
        
        while(1)
        {
            printf("Inserisci il primo carattere: ");
            scanf("%c", &out_buf[0]);
            clean_stdin();        
            printf("Inserisci il secondo carattere: ");
            scanf("%c", &out_buf[1]);
            clean_stdin();
            
            out_buf[2] = '\0';
            if(send(clientSocket , out_buf , BUF_SIZE , 0) < 0)
            {
                puts("Send failed");
                exit(3);
            }
            puts("Sent message: ");
            puts(out_buf);        
            
            recv(clientSocket , in_buf , BUF_SIZE , 0);
            while(strcmp(in_buf, "OC") != 0)
            {
                sleep(1);
                recv(clientSocket , in_buf, BUF_SIZE, 0);
            }
            puts(out_buf);
            recv(clientSocket , in_buf , BUF_SIZE , 0);
            while(strlen(in_buf) != 1)
            {
                sleep(1);
                recv(clientSocket , in_buf, BUF_SIZE, 0);
            }
            puts(out_buf);
            printf("La distanza di Hamming tra i caratteri \"%c\" e \"%c\" è %c\n", out_buf[0], out_buf[1], in_buf[0]);
            if(out_buf[0] == '0' && out_buf[1] == '0')
                break;
            else
            {
                if(recv(clientSocket , in_buf, BUF_SIZE , 0) <= 0 || strcmp(in_buf, "OK") != 0)
                {
                    puts("recv failed");
                    exit(2);
                }
            }
        }
         
        close(clientSocket);
        return TRUE;
    }
    e il codice del server concorrente usando il thread
    #include <stdio.h>      
    #include <stdlib.h>     
    #include <string.h>     
    #include <fcntl.h>      
    #include <sys/stat.h>   
    #include <errno.h>
    
    /* FOR BSD UNIX/LINUX  ---------------------------------------------------- */
    #include <sys/types.h>    
    #include <netinet/in.h>   
    #include <sys/socket.h>   
    #include <arpa/inet.h>    
    #include <sched.h>  
    #include <pthread.h>
    #include <signal.h> 
    #include <semaphore.h> 
    
    #define BUF_SIZE            1024    // buffer size in bytes
    #define PORT_NUM            6110    // Port number for a Web server (TCP 5080)
    #define PEND_CONNECTIONS    100    // pending connections to hold 
    #define TRUE                  1
    #define FALSE                 0
    
    int readLine(int fd, char data[])
    {
       size_t len = 0;
       while (len < BUF_SIZE)
       {
          char c;
          int ret = read(fd, &c, 1);
          if (ret < 0)
          {
              data[len] = 0;
              return len; // EOF reached
          }
          if (c == '\n')
          {
              data[len] = 0;
              return len; // EOF reached
          }
          data[len++] = c;
       }
    }
    
    int hammingDistance(int x, int y)
    {
        int h = 0;
        int t = x;
    	int s = y;
        
    	while (t > 0 || s > 0)
        {
    	  if ((t % 2) != (s % 2)) 
    	    h++;
    	  t /= 2;
    	  s /= 2; 
    	}
        
        return h;
    }
    
    void* threadFunction(void* args)
    {
        unsigned int    clientSocket;        //copy socket
        char          in_buf[BUF_SIZE];          // Input buffer for GET resquest
        char          out_buf[BUF_SIZE];          // Output buffer for HTML response
        int hamming;
        
        clientSocket = *(unsigned int *)args;        // copy the socket
        
        strncpy(out_buf, "OK", BUF_SIZE);
        send(clientSocket, out_buf, BUF_SIZE, 0);
        puts(out_buf);
        //send(clientSocket , out_buf , BUF_SIZE , 0);
        
        while(1)
        {
            while(strlen(in_buf) != 2)
                recv(clientSocket , in_buf , BUF_SIZE , 0);
            strncpy(out_buf, "OC", BUF_SIZE);
            send(clientSocket, out_buf , BUF_SIZE , 0);
            puts(out_buf);
            hamming = hammingDistance(in_buf[0] - '0', in_buf[1] - '0');
            out_buf[0] = '0' + hamming;
            out_buf[1] = '\0';
            puts(out_buf);
            send(clientSocket, out_buf , BUF_SIZE , 0);
            puts(out_buf);
            if(in_buf[0] == '0' && in_buf[1] == '0')
                break;
            else
            {
                strncpy(out_buf, "OK", BUF_SIZE);
                send(clientSocket , out_buf , BUF_SIZE , 0);
                puts(out_buf);
                in_buf[1] = '\0';
            }
        }
        close(clientSocket);
    }
    
    int main(void)
    {
        unsigned int          serverSocket;              // Server socket descriptor
        struct sockaddr_in    serverAddress;            // Server Internet address
        unsigned int          clientSocket;          // Client socket descriptor
        struct sockaddr_in    clientAddress;            // Client Internet address
        int                   clientAddressLength;              // Internet address length
    
        unsigned int          ids;                    // holds thread args
        pthread_t            threads;                // Thread ID (used by OS)
    
        serverSocket = socket(AF_INET , SOCK_STREAM , IPPROTO_TCP);
        serverAddress.sin_family = AF_INET;
        serverAddress.sin_addr.s_addr = INADDR_ANY;
        serverAddress.sin_port = htons(PORT_NUM);
    
        bind(serverSocket,(struct sockaddr *)&serverAddress , sizeof(struct sockaddr));
        
        listen(serverSocket, PEND_CONNECTIONS);
    
        while(TRUE)
        {
            printf("my server is ready ...\n");  
    
            /* wait for the next client to arrive -------------- */
            clientAddressLength = sizeof(clientAddress);
            clientSocket = accept(serverSocket, (struct sockaddr *)&clientAddress, &clientAddressLength);
    
            printf("a new client arrives ...\n");  
    
            if (clientSocket == FALSE)
            {
                printf("ERROR - Unable to create socket \n");
                exit(FALSE);
            }
            else
            {
                ids = clientSocket;
                pthread_create(&threads, NULL, threadFunction, &ids);
            }
        }
    
        close (serverSocket);
        return (TRUE);
    }
    Dov'è l'errore?
Devi accedere o registrarti per scrivere nel forum
2 risposte