Ciao oregon il mio ambiente di lavoro e osx.
Sto studiando da poco il protocollo TCP e dovrei fare questo esercizio in c.
Il codice del client è il seguente:
codice:
#include <sys/types.h>#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define PROTOPORT 5193 /* default port number */
extern int errno;
char localhost[] = "127.0.0.1"; /* localhost è una variabile che tiene traccia
dell'indirizzo di default,questo è un'indirizzo
particolare perche rappresenta su qualsiasi
macchina, la macchina stessa. Mi permette
la comunicazione tra processi che sono sulla
stessa macchina*/
int main(int argc, char *argv[]) { /* Il primo parametro, se specificato da riga di comando
va a sostituire l'indirizzo IP di default, invece
il secondo parametro se specificato, va a sostituire
il numero di porta di default*/
struct sockaddr_in sad; /* structure to hold an IP address del server */
int sd; /* socket descriptor */
int port; /* protocol port number, che può essere messo di
default o da riga di comando */
int n; /* number of characters read */
char buf[1000]; /* buffer for storing data from the server */
char *host;
memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */
sad.sin_family = AF_INET; /* set family to Internet */
/* Questi due if di seguito, vanno a sostituire, rispettivamente, il numero di porta
e l'indirizzo IP, se e solo se sono specificati come parametri del main altrimenti
vengono utilizzati quelli di default*/
if (argc > 2) { /* if protocol port specified */
port = atoi(argv[2]); /* convert to binary */
} else {
port = PROTOPORT; /* use default port number */
}
if (port > 0) /* test for legal value */
sad.sin_port = htons((u_short)port);
else { /* print error message and exit */
fprintf(stderr,"bad port number %s\n",argv[2]);
exit(1);
}
/* Check host argument and assign host name. */
if (argc > 1) {
host = argv[1]; /* if host argument specified */
} else {
host = localhost;
}
sad.sin_addr.s_addr = inet_addr(host);
/* Create a socket. */
sd = socket(PF_INET, SOCK_STREAM, 0);
if (sd < 0) {
fprintf(stderr, "socket creation failed\n");
exit(1);
}
if (connect(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
fprintf(stderr, "connect failed\n");
exit(1);
}
n = read(sd, buf, sizeof(buf));
while (n > 0) {
write(1, buf, n);
n = read(sd, buf, sizeof(buf));
}
/* Close the socket. */
close(sd);
/* Terminate the client program gracefully. */
exit(0);
}
Il codice del server è questo:
codice:
#include <sys/types.h>#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define PROTOPORT 5193 /* numero di porta di default */
#define QLEN 6 /* coda richieste di connessione */
int visits = 0; /* variabile che conta le connessioni del client al server */
int main(int argc, char *argv[]) {
struct sockaddr_in sad; /* struttura sockaddr_in,indirizzo del server */
struct sockaddr_in cad; /* struttura sockaddr_in, indirizzo del client */
int sd, sd2; /* due descrittori socket,perche stiamo utilizzando
un modello orientato ai flussi,quindi uno sta a
rappresentare la socket di contatto e l'altra la
socket di connessione */
int port; /* protocol port number */
int alen; /* length of address */
char buf[1000]; /* buffer utilizzato per inviare il messaggio */
memset((char *)&sad, 0, sizeof(sad)); /* clear sockaddr s. */
sad.sin_family = AF_INET; /* set family to Internet */
sad.sin_addr.s_addr = htonl(INADDR_ANY); /* set the local IP addr */
if (argc > 1) { /* se l'argomento specificato è
maggiore di 1, vuol dire che è stato
specificato un numero di porta da riga
di comando il quale viene poi convertito
in una stringa */
port = atoi(argv[1]);
} else {
port = PROTOPORT; /* altrimenti viene usato il numero
di porta di default */
}
/* Verify port number */
/* … */
sad.sin_port = htons((u_short)port); /* Assegniamo quindi il numero di
porta,e lo convertiamo con una
rappresentazione esterna*/
/* A questo punto abbiamo pronto l'indirizzo di trasporto*/
/* Creiamo la socket */
sd = socket(PF_INET, SOCK_STREAM, 0);
if (sd < 0) {
fprintf(stderr, "socket creation failed\n");
exit(1);
}
/* Effettua la Bind sull'indirizzo locale della socket */
if (bind(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
fprintf(stderr,"bind failed\n");
exit(1);
}
/* Da questo momento in poi, se la Bind non è fallita,la socket
del server può accettare connessioni, e attraverso la listen si va a
specificare la coda di lunghezza delle connessioni */
if (listen(sd, QLEN) < 0) {
fprintf(stderr,"listen failed\n");
exit(1);
}
/* Vogliamo che il server rimanga in ascolto del client teoricamente
all'infinito per questo utilizziamo il ciclo while*/
while (1) {
alen = sizeof(cad);
/* Viene invocata la funzione accept sul descrittore sd e restituisce
ancora un'intero; estra una connessione dalla coda di connessioni
la quale duplica la struttura di origine e si completa con le
informazioni del client che si è connesso al server
La conversazione avverrà attraverso la socket sd2*/
if ( (sd2=accept(sd, (struct sockaddr *)&cad, &alen)) < 0) {
fprintf(stderr, "accept failed\n");
exit(1);
}
/* Dopo l'accept posso utilizzare la read; nel caso specipico il contatto
è avvenuto tramite la connessione, quindi abbiamo sfruttato la richiesta di
connessione la quale mi ha garantito il contatto,quindi andiamo a incrementare
la variabile visit e andiamo a scrivere il messaggio di risposta*/
visits++;
/*funzione fprintf scrive sul file, sprintf scrive su un buffer e bisogna
specificare sempre il nome dell'array prima di stampare a video ciò che
si desidera, in questo caso il nome dell'array è buf*/
sprintf(buf, "This server has been contacted %d time%s\n", visits, visits==1 ? "." : "s.");
/* Con la funzione write, scriverò nel buffer la stringa,questa roba si
trova nel buffer associata della socket di connessione sd2*/
write(sd2, buf, strlen(buf));
close (sd2); /* Sto chiudendo la socket di connessione utilizzata
per conversare con lo specifico client. La variabile sarà disponibile
per un'ulteriore connessione con un'altro client.
sd non l'abbiamo chiusa, altrimenti chiuderemo la socket del server.*/
}
}
Praticamente in questo modo ogni volta che avvio il client, il server gli invia un messaggio indicando il numero di volte che il server è stato contattato.
Ora dovrei modificarlo, chiedendo al client di inserire il mio nome e successivamente quando il client contatta il server deve inviare al client un messaggio nel quale oltre a dire quante volte è stato contattato il server, nel messaggio deve comparire il mio nome, esempio "gigi ha contattato il server 5 volte"