PDA

Visualizza la versione completa : [C] Programmazione di rete


nicolo_conte
02-04-2007, 11:45
Ciao a tutti,
devo creare il seguente programma:



Progettare, codificare in linguaggio C e collaudare un programma eseguito da un processo padre SRV e da due processi server SRV_X (1 o 2).
Ciascun processo SRV_X gestisce un canale CNL_X tra se stesso e un cliente di verifica CLI_X. Il problema utilizza l’allegato ‘term.txt’:

1)SRV ha il ruolo di server studente e deve servire in parallelo due richieste di servizio da parte di due clienti di verifica diversi CLI_X.
2)SRV si pone in attesa di collegamento da parte dei processi CLI_X sulla porta TCP XXXXX.
3)Per una generica richiesta di connessione X, SVR_X utilizza il canale di rete CNL_X aperto con CLI_X per eseguire i processi seguenti:

a)SRV_X entra in un ciclo nel quale svolge le seguenti azioni:

I)Riceve da CLI_X, sul canale CNL_X, una sequenza di caratteri terminata dal carattere newline (‘\n’) e di lunghezza massima 5. Tale sequenza, convertita in formato numerico, rappresenta un indice IDX (vedi nota per la conversione).
II)Apre il file ‘term.txt’, ricevuto come allegato al testo del problema, legge il carattere alla posizione IDX e lo memorizza, quindi chiude il file. Il carattere letto, indicato nel seguito come CH_TERM, ha il significato di ‘terminatore’ per i messaggi successivi.
III)Riceve da CLI_X, sul canale CNL_X, una sequenza di caratteri CH_SEQ di lunghezza max 64, il cui ultimo carattere è il ‘terminatore’ CH_TERM precedentemente letto da file.
IV)Conta il numero di caratteri della sequenza CH_SEQ, compreso il carattere ‘terminatore’ CH_TERM.
V)Invia a CLI_X, sullo stesso canale CNL_X, il numero di caratteri ricevuti, compreso il carattere ‘terminatore’ CH_TERM (vedi nota per la conversione).

b)Il ciclo termina quando SRV_X legge dal file un carattere terminatore CH_TERM uguale a ‘q’.
c)Il processo SRV_X chiude il canale di rete CNL_X e termina.

4)Il processo SRV_X non attende il termine dei servizi, ma chiude il canale usato e termina.

Si tenga presente che:

I clienti di verifica CLI_X funzionano sempre correttamente.
I clienti di verifica CLI_X si aspettano di ricevere la corretta lunghezza della stringa inviata CH_SEQ.
Per la conversione di una sequenza di caratteri numerici nel corrispondente valore interno si utilizzi la funzione:
int atoi(char *str);

Il numero da inviare deve essere convertito in una sequenza di caratteri terminata da newline (‘\n’). Utilizzare per la conversione la funzione ‘sprintf’:

int sprintf(char *buffer, char *format, [argument, …]);

Per la conversione utilizzare come specificatore di formato la stringa “%d\n”.
Se i clienti di verifica CLI ricevono dati diversi da quelli attesi, essi chiudono il canale CNL e terminano immediatamente.


una volta compilato il programma nel laboratorio vi è un verificatore che "verifiuca" il corretto funzionamento del programma. Se riusciste a darmi una mano sarebbe un sollievo visto che ormai ci sto "sbattendo la testa" da una settimana! Che errori vi sono?

nicolo_conte
02-04-2007, 11:46
E questo è il codice da me scritto:



#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define PORT 4000
#define MAXCONN 5

void addr_initialize(struct sockaddr_in * pt, unsigned int TCP_port, unsigned int IP_addr){

pt->sin_family = AF_INET;
pt->sin_port = htons ((unsigned short int) TCP_port);
pt->sin_addr.s_addr = IP_addr;
}

int main (){

FILE *file; /*INIZIO DICHIARAZIONE VARIABILI*/
struct sockaddr_in server_addr, cli_addr;
int client_len = sizeof (cli_addr);
int sd, new_sd, i, u, m, pid, teminatore;
char ch_term [5], ch_recv[64], num_char[10]; /*FINE DICHIARAZIONE VARIABILI*/

addr_initialize (&server_addr, PORT, INADDR_ANY);
sd = socket (AF_INET, SOCK_STREAM, 0); /*CREAZIONE DEL SOCKET SD*/
bind (sd, (struct sockaddr *) &server_addr, sizeof (server_addr);
listen (sd, MAXCONN); /*SI PONE IN ATTESA DI EVENTUALI CONNESSIONI*/

for (i = 0; i < 2; i++){ /*ACCETTA DUE CONNESSIONI*/

new_sd = accept (sd, (struct sockaddr *) &client_addr, &client_len);

pid = fork (); /*ESECUZIONE DELLA FUNZIONE FORK*/

if (pid == 0){ /*PROCESSO FIGLIO*/

for (u = 0; ch_term [u] != '\n'; u++){ /*RICEVE UN CARATTERE ALLA VOLTA FINO A '\N'*/
recv (new_sd, ch_term [u], 1, 0); /* E LO IMMAGAZZINA IN CH_TERM*/
}

terminatore = atoi (ch_term); /*TRASFORMA IN INT CH_TERM*/

file = fopen ("~/term.txt", "r"); /*APRE IL FILE TERM.TXT IN SOLA LETTURA*/
fseek (file, terminatore, SEEK_SET); /*SI SPOSTA DI UN VALORE TERMINATORE NEL FILE*/
fscanf (...) /*COME LEGGO IL CARATTERE????*/

for (m = 0; ch_recv [m] != /*dal terminatore*/ || ch_term [m] != 'q'; m++){
recv (new_sd, ch_recv[m], 1, 0);
}

sprintf (num_char, "%d\n", m);

send (num_char, m, 10, 0);

close (new_sd);

exit (0);
}

else close (sd);
}
}

nicolo_conte
02-04-2007, 11:47
sono un pò titubante sul modo di ottenere il carattere dal file e soprattutto se i cicli che ho creato portano effettivamente a qualcosa! Grazie mille a tutti coloro che avranno la pazienza di aiutarmi :ciauz:

nicolo_conte
02-04-2007, 21:51
nessuno riesce a darmi anche una piccola dritta?

donato.sciarra
02-04-2007, 22:01
come disse un certo spinaza usa le printf. . . :zizi: e poi . . . vabbe no comment

nicolo_conte
02-04-2007, 22:24
ci avevo pensato...ma il fatto è che viene stampata la prima printf ma le successive no (anche se la connessione avviene e il programma procede)! Che fare?

donato.sciarra
02-04-2007, 23:03
1) per leggere il carattere puoi usare

CH_TERM = fgetc(FILE *fptr);/*controlla la sintassi da terminale o su google scrivendo "man fgetc"*/

in questo modo leggi il carattere alla posizione nel file data dalla fseek....


2) stampa passo passo le variabili che ottieni (caratteri ricevuti, conversioni ecc.), almeno cosi capisci dove si blocca. . .

potresti avere problemi con i buffer svuotali con fflush o con degli \n alla fine d ogni printf . . .

nicolo_conte
02-04-2007, 23:10
Originariamente inviato da donato.sciarra
1) per leggere il carattere puoi usare

CH_TERM = fgetc(FILE *fptr);/*controlla la sintassi da terminale o su google scrivendo "man fgetc"*/

in questo modo leggi il carattere alla posizione nel file data dalla fseek....


2) stampa passo passo le variabili che ottieni (caratteri ricevuti, conversioni ecc.), almeno cosi capisci dove si blocca. . .

potresti avere problemi con i buffer svuotali con fflush o con degli \n alla fine d ogni printf . . .

ok grazie mille, usando fgetc ho letto che ritorna un intero quindi dovrei riconvertirlo in una lettera giusto? Come posso fare? Grazie ancora per la pazienza :ciauz:

donato.sciarra
02-04-2007, 23:14
non hai finito di leggere ti manca il pezzo dove parla dei caratteri di ritorno . . .



riporto:

If successful, these routines return the next requested object from the stream. Character values are returned as an unsigned char converted to an int.



CH_TERM e' già di tipo carattere . . . non devi fare assolutamente niente !

nicolo_conte
03-04-2007, 00:06
opppps...è vero...scusa! Nel sito che ho visitato non era specificato...grazie ancora!

Loading