PDA

View Full Version : client server scampi di messaggi


moskino85
12-10-2013, 09:58
Ciao amici, spero di postare la mia domanda nella sezione giusta
Sto svolgendo un'esercizio in c che consiste nel creare un sorta di chat tra il client e il server, in pratica si scambiano messaggi fino a quando non si preme un tasto per terminare la conversazione.
Ho provato ad implementare lo scambio di messaggi e ci sono riuscito, il problema sorge quando voglio far terminar la conversazione digitando ad esempio -(il trattino). Qualcuno gentilmente potrebbe darmi un consiglio.

L'implementazione del client è:

#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"; /* default host name */

int main(int argc, char *argv[]) {
struct sockaddr_in sad; /* structure to hold an IP address */
int sd; /* socket descriptor */
int port; /* protocol port number */
int n; /* number of characters read */
char buf[1000]; /* buffer for storing data from the server */
char *host;
int status = 1; /*status = write*/


memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */
sad.sin_family = AF_INET; /* set family to Internet */

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
",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
");
exit(1);
}

if (connect(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
fprintf(stderr, "connect failed
");
exit(1);
}
switch(status) {
case 1:
printf("(CLIENT) Scrivi il messaggio: ");
fgets(buf,999, stdin); /*legge una linea dallo standard output*/
n = write(sd, buf, sizeof(buf));
status = 2;
break;
case 2:
n = read(sd, buf, sizeof(buf));
printf("(CLIENT) Ecco il messaggio ricevuto dal server: %s
", buf);
status = 1;
break;
}
close(sd);
/* Terminate the client program gracefully. */
exit(0);
}


L'implementazione del server è:

#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 protocol port number */
#define QLEN 6 /* size of request queue */



int main(int argc, char *argv[]) {
struct sockaddr_in sad; /* s. to hold server's address */
struct sockaddr_in cad; /* s. to hold client's address */
int sd, sd2; /* socket descriptors */
int port; /* protocol port number */
int alen; /* length of address */
char buf[1000]; /* buffer for sending data */
int n;
char *messaggio_ricevuto = "FINE COMUNICAZIONE";
int status = 2;

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) { /* if argument specified */
port = atoi(argv[1]); /* convert argument to binary */
} else {
port = PROTOPORT; /* use default port number */
}

/* Verify port number */
/* … */

sad.sin_port = htons((u_short)port);

/* Create a socket */
sd = socket(PF_INET, SOCK_STREAM, 0);

if (sd < 0) {
fprintf(stderr, "socket creation failed
");
exit(1);
}
/* Bind a local address to the socket */
if (bind(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
fprintf(stderr,"bind failed
");
exit(1);
}
/* Specify the size of the request queue */
if (listen(sd, QLEN) < 0) {
fprintf(stderr,"listen failed
");
exit(1);
}
while((sd2 = accept(sd, (struct sockaddr *)&cad, &alen)) > -1) {
switch(status) {
case 1:
printf("(SERVER) Scrivi il messaggio: ");
fgets(buf, 999, stdin);
n = write(sd2, buf, sizeof(buf));
status = 2;
break;
case 2 :
n = read(sd2, buf, sizeof(buf));
printf("(SERVER) Ecco il messaggio ricevuto dal client: %s
", buf);
status = 1;
break;
}
close (sd2);
}}

Grazie a chiunque mi risponderà

Oceans11
12-10-2013, 12:40
prova a descrivere il problema, è altamente probabile che ne saltino fuori altri di cui non ti sei accorto. (suggerimento: il protocollo di comunicazione da te stabilito non mi pare "robusto")

moskino85
12-10-2013, 13:24
Ciao Oceans11 sinceramente è la prima volta che sto implementando un client-server per questo risulta poco robusto.Comunque il mio problema è che il client e il server si inviano messaggi a vicenda e fin qui sembra che ci sono riuscito.Ora l'esercizio chiede che se il client o il server vogliono terminare questa comunicazione, bisogna premere un carattere ad esempio il trattino - in modo tale che la comunicazione tra i due termini.Ho provato a fare delle prove ma non ci sono riuscito
Ad esempio ho fatto questa prova, (ora non so se ho impostato correttamente ciò che desidero è l'ho sbagliato a posizionare nel corpo del main comunque ho scritto una cosa del genere):

char c = '-'; //ho dichiarato questo carattere
char buffer[256]; // questo è il buffer che utilizzo per scrivere il messaggio
if(strcmp(buffer,c)) {
exit(0);
}

Ho fatto una prova di questo tipo ma non ho avuto i risultati desiderati.Tu cosa mi suggeriresti?

Oceans11
12-10-2013, 16:23
allora, incomincio a dirti quali sono le cose che non vanno man mano che le vedo

* il client non sta ciclando, fa un solo invio e una sola ricezione (errore logico del tuo protocollo???)

* attento a quando fai la read, non è vero che se chiedi di leggere 100 byte ti vengono letti 100 byte.

* il secondo parametro di strcmp non può essere un char ma deve essere un puntatore a char

beh, intanto mi fermo qui.
Per la robustezza del protocollo mi riferivo ai primi 2 punti. Devi cercare di capire come funzionano le socket e pensare ad un protocollo adatto, ad esempio, se la read non dà garanzie sul numero di byte letti, se non sono tutti dovresti rileggerli ;).

Sei uno dei pochi "novizi" (ps: lo sono anche io) che vedo utilizzare correttamente il tipo di dato restituito dalle funzioni di libreria del c.

moskino85
15-10-2013, 14:33
Ciao Oceans, comunque poi ho risolto in questo modo:

questa è la parte del client

#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"; /* default host name */

int main(int argc, char *argv[]) {
struct sockaddr_in sad; /* structure to hold an IP address */
int sd; /* socket descriptor */
int port; /* protocol port number */
int n; /* number of characters read */
char buf[1000]; /* buffer for storing data from the server */
char *host;
int status = 1; /*status = write*/
int j = 0;
char *messaggio_finale = "IL CLIENT SI E DISCONNESSO";

memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */
sad.sin_family = AF_INET; /* set family to Internet */

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);
}

while(status != 0) {

switch(status) {
case 1:
printf("(CLIENT) Scrivi il messaggio (premi q per terminare): ");
fgets(buf,999, stdin); /*legge una linea dallo standard output*/
if(buf[j] == 'q') {
n = write(sd, messaggio_finale, strlen(messaggio_finale)+1);
close(sd);
exit(0);
}
n = write(sd, buf, sizeof(buf));

status = 2;
break;
case 2:
n = read(sd, buf, sizeof(buf));


printf("(CLIENT) Ecco il messaggio ricevuto dal server: %s\n", buf);
status = 1;
break;
}}
close(sd);
/* Terminate the client program gracefully. */
exit(0);
}


e per quanto riguarda il server:


#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 protocol port number */
#define QLEN 6 /* size of request queue */



int main(int argc, char *argv[]) {
struct sockaddr_in sad; /* s. to hold server's address */
struct sockaddr_in cad; /* s. to hold client's address */
int sd, sd2; /* socket descriptors */
int port; /* protocol port number */
int alen; /* length of address */
char buf[1000]; /* buffer for sending data */
int n;
int status = 2;
int j = 0;
char *messaggio_finale = "IL SERVER SI E DISCONNESSO";

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) { /* if argument specified */
port = atoi(argv[1]); /* convert argument to binary */
} else {
port = PROTOPORT; /* use default port number */
}

/* Verify port number */
/* … */

sad.sin_port = htons((u_short)port);

/* Create a socket */
sd = socket(PF_INET, SOCK_STREAM, 0);

if (sd < 0) {
fprintf(stderr, "socket creation failed\n");
exit(1);
}
/* Bind a local address to the socket */
if (bind(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
fprintf(stderr,"bind failed\n");
exit(1);
}
/* Specify the size of the request queue */
if (listen(sd, QLEN) < 0) {
fprintf(stderr,"listen failed\n");
exit(1);
}
while((sd2 = accept(sd, (struct sockaddr *)&cad, &alen)) > -1) {
while(status != 0) {
switch(status) {
case 1:
printf("(SERVER) Scrivi il messaggio (premi q per terminare): ");
fgets(buf, 999, stdin);
if(buf[j] == 'q') {
n = write(sd2, messaggio_finale, strlen(messaggio_finale)+1);
close(sd2);
exit(0);
}
n = write(sd2, buf, sizeof(buf));
status = 2;
break;
case 2 :
n = read(sd2, buf, sizeof(buf));

printf("(SERVER) Ecco il messaggio ricevuto dal client: %s\n", buf);
status = 1;
break;
}}
close (sd2);
}}

moskino85
16-10-2013, 11:41
Oceans11 scusami se ti disturbo nuovamente, ma dovrei fare lo stesso esercizio in java, l'unico problema che sto riscontrando e come utilizzare gli interi,il prof ha detto di utilizzare DataOutputStream e DataInputStream ma non riesco a farlo...hai qualche esempio a riguardo così da potermi rendere conto di come si utilizza?grazie ancora.