JcBobo
29-04-2013, 14:01
buon giorno a tutti sono uno studente di ing. informatica sto frequentando un corso di programmazione distribuita e mi è stato chiesto di creare una coppia server-client dove
il client (tramite riga di comando) possa richiedere al server un file tramite il comando GET nomefile (seguito da \n)
quando "finito" di richiedere files tramite ll comanod QUIT il client lo segnali al server e chiuda la connessione
il server una volta ricevuto un comando deve verificarne la correttezza (QUIT o GET) dopo di che se il file esiste inviarlo al client e restare in attesa per ulteriori richieste
in caso di errore (file nn esistente/ comando errato) segnalare errore e chiudere la connessione.
testo:
Sviluppare un server TCP (in ascolto sulla porta specificata come primo parametro sulla riga di
comando) che accetti richieste di trasferimento file da client ed invii il file richiesto.
Sviluppare un client che si colleghi ad un server TCP (all’indirizzo e porta specificati come primo e
secondo parametro sulla riga di comando) per richiedere dei file e memorizzarli localmente. I nomi
dei file da richiedere vengono forniti su standard input, uno per riga. Ogni file richiesto deve essere
salvato localmente e deve essere fornito su standard output un messaggio circa l’avvenuto
trasferimento, con nome e dimensione del file.
Per richiedere un file il client invia al server i tre caratteri ASCII “GET” seguiti dal nome del file
(max 64 caratteri) e da CR LF (senza alcun spazio):
GET nomefile CR LF
Il server risponde inviando:
+OK CR LF
seguito dal numero di byte (intero su 32 bit in formato di rete) e quindi dai byte del file in oggetto.
Il client può richiedere più file inviando più comandi GET. Quando intende terminare la
comunicazione invia:
QUIT CR LF
e chiude il canale.
In caso di errore (es. comando illegale, file inesistente) il server risponde sempre con
-ERR CR LF
e quindi chiude il canale col client.
Provare a collegare il proprio client col server sviluppato da un altro gruppo e viceversa.
Mentre è in corso un collegamento provare ad attivare un secondo client verso il medesimo server.
Provare ad attivare sul medesimo nodo una seconda istanza del server sulla medesima porta.
Provare a collegare il client ad un indirizzo non raggiungibile.
Provare a collegare il client ad un indirizzo esistente ma ad una porta su cui il server non è in
ascolto.
Provare a disattivare il server (battendo ^C nella sua finestra) mentre un client è collegato.
CLIENT
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <unistd.h>
#include <error.h>
#include <errno.h>
//define
#define MAXLENFILENAME 64
#define MAXLENMESSAGE MAXLENFILENAME+3+1+2 // filename+ get + \0+\r\n
#define MAXLENREPLY 15
#define ATTEMPT 5 //tentativi
//function prototipie
int writen(int s, char *, size_t maxlen);
int readline (int s, char *ptr, size_t maxlen);
int connectionOpen(int s);
int ConnectSocket(int socket,struct sockaddr_in targetaddress);
int main (int argc, char **argv){
int client_socket=-2; /*socket */
struct sockaddr_in servaddr; /* server address structure */
struct in_addr ipaddress; // server ipaddress
int i;
char command[MAXLENMESSAGE];
char reply[MAXLENREPLY],tmp[MAXLENREPLY];
int reply_dim,fd;
char filename[MAXLENFILENAME];
uint32_t file_size;
int res;
//asd
// check imput parametre
if(argc !=3){
fprintf(stderr,"usage: %s server_addresss port_num",argv[0]);
exit(1);
}
// socket creation
i=0;
do{
client_socket=socket(AF_INET, SOCK_STREAM,IPPROTO_TCP); //AF_INET internet SOCK_STREAM TCP
printf("tentativo %d socket: %d\n",i,client_socket);
i++;
// manage error loocking errno
} while(!client_socket||i==ATTEMPT);
if((i==ATTEMPT)&&(client_socket==0)){
fprintf(stderr,"impossibile create the socket");
exit(1);
}
//server address creation
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&ipaddress);
servaddr.sin_addr=ipaddress;
// connect the socket
if((res=ConnectSocket(client_socket,servaddr))!=0){
fprintf(stderr,"is impossible to connect res:%d\n",res);
exit(1);
}
do{
if((connectionOpen(client_socket))==-1){ // se server chiuso connessione la riapro
if(ConnectSocket(client_socket,servaddr)!=0){
perror("is impossible to connect\n");
}
}
printf("insert a command: GET filename or QUIT to exit\n");
fgets(command,MAXLENMESSAGE,stdin);
fprintf(stdout,"\n\ncommand is: %s\n",command);
//printf("editing command \n");
//strcat(command,"\n");
//printf("edited command is %s\n",command);
writen(client_socket,command,sizeof(command));
if(strncmp(command,"QUIT",4)!=0 ){ // wait the reply from the server and do consequently
sscanf(command,"%s%s",tmp,filename);
sleep(1);
reply_dim=readline(client_socket,reply,sizeof(reply));
reply[reply_dim-1]='\0';//++?
fprintf(stdout,"%s",reply);
char filesize_s[10];
readline(client_socket,filesize_s,sizeof(filesize_s));
fprintf(stdout,"%s",filesize_s);
file_size=atoi(filesize_s);
fprintf(stdout,"%s size is:",filename,file_size);
if(reply[0]=='-'){//error keyword or file not present
fprintf(stderr,"the server reply with error code\n");
close(client_socket);
}
else{ // file presente
//sscanf(reply,"%s%d",tmp,&file_size);
//file_size=(file_size);
//ora devo ricevere il file
printf("filename %s file_size %d\n",filename,file_size);
fd=creat(filename,S_IWRITE);
printf("file created\n");
if((res=sendfile(fd,client_socket,0,file_size))==-1){ // modificare con dimensione letta=dimensione file
printf("error during trasfer file try again\n");
fprintf(stderr,"%s",strerror(errno));
unlink(filename);
}
else{
printf("the transfer of %s is completed\n",filename);
}
close(fd);
}
}
else{// comando=QUIT
close(client_socket);
}
}
while(strcmp(command,"QUIT"));
}
//this function return 0 if the connection is open 1 otherwise
int connectionOpen(int s){
int error = 0;
socklen_t len = sizeof (error);
int retval = getsockopt (s, SOL_SOCKET, SO_ERROR, &error, &len );
if (retval==0)
return 0;
else return -1;
}
// this function connect the socket end return the value
int ConnectSocket(int socket,struct sockaddr_in targetaddress){
int i=0;
int result;
while((i==ATTEMPT)||(result=(connect(socket,(struct sockaddr *)&targetaddress,sizeof(targetaddress)))!=0)){ //try ATTEMPT times to connect
i++;
// manage error loocking errno
}
return result;
}
int writen(int s, char *ptr, size_t nbytes)
{
size_t nleft;
ssize_t nwritten;
for (nleft=nbytes; nleft > 0; )
{
nwritten = send(s, ptr, nleft, 0);
if (nwritten <=0)
return (nwritten);
else
{
nleft -= nwritten;
ptr += nwritten;
}
}
return (nbytes - nleft);
}
/* Reads a line from stream socket s to buffer ptr
The line is stored in ptr including the final '\n'
At most maxlen chasracters are read
return value:
the number of readed character
-1 if a error occurred
0 with *ptr=0 if the connection is closed by party
*/
int readline (int s, char *ptr, size_t maxlen)
{
size_t n;
ssize_t nread;
char c;
for (n=1; n<maxlen; n++)
{
nread=recv(s, &c, 1, 0);
if (nread == 1)
{
*ptr++ = c;
if (c == '\n')
break;
}
else if (nread == 0) /* connection closed by party */
{
*ptr = 0;
return (n-1);
}
else /* error */
return (-1);
}
*ptr = 0;
return (n);
}
SERVER
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <error.h>
//define
#define MAXLENFILENAME 64
#define MAXLENMESSAGE MAXLENFILENAME+3+1+2 // filename+ get + \0+\r\n
#define MAXLENREPLY 15
#define QUEQUEDIM 5
#define ATTEMPT 5 //tentativi
//function prototipie
int writen(int s, char *, size_t maxlen);
int readline (int s, char *ptr, size_t maxlen);
//int connectionOpen(int s);
int main(int argc ,char **argv){
int server_socket,accepted_socket;
int fd;
int i,res;
struct sockaddr_in addr;
struct sockaddr addr_a;
struct stat buff;
socklen_t addr_len_a;
char message[MAXLENMESSAGE],filename[MAXLENFILENAME],tmp[MAXLENMESSAGE];
if(argc!=2){
fprintf(stderr,"using %s port_number",argv[0]);
exit(-1);
}
//creare socket
i=0;
do{
server_socket=socket(AF_INET, SOCK_STREAM,IPPROTO_TCP); //AF_INET internet SOCK_STREAM TCP
printf("tentativo %d socket: %d\n",i,server_socket);
i++;
// manage error loocking errno
} while(!server_socket||i==ATTEMPT);
if((i==ATTEMPT)&&(server_socket==0)){
perror("impossibile create the socket");
}
// address for bind creation
addr.sin_family = AF_INET;
addr.sin_port = htons(atoi(argv[1]));
addr.sin_addr.s_addr= htonl (INADDR_ANY);
//bind
i=0;
do{
res=bind(server_socket,(struct sockaddr*)&addr,sizeof(addr));
// manage error
fprintf(stderr,"errore bind %d error: %d \n",res,errno);
i++;
}
while((res!=0||i==ATTEMPT));
printf("bind result %d\n",res);
//attesa connessione and accettare connessione
i=0;
while((res=listen(server_socket,QUEQUEDIM))!=0||i==ATTEMPT){
fprintf(stderr,"errore durante la listen res: %d i:%d\n",res,i);
i++;
}
i=0;
printf("listen completed %d \n",res);
while( (accepted_socket=accept(server_socket,&addr_a,&addr_len_a))<0||(i==ATTEMPT)){//accept ritorna int>0 (socket descriptor)
fprintf(stderr,"errore durante la accept return value %d i:%d\n",accepted_socket,i);
i++;
}
printf("tentativi accept terminati\n");
if((i==ATTEMPT)&&(res==-1)){
fprintf(stderr,"impossible accept connection\n");
exit(1);
}
//ricevere richiesta
printf("accept eseguita\n");
res=0;
i++;
while(((res=readline(accepted_socket,message,MAXLENMESSAGE))<0)||(i==ATTEMPT)){
fprintf(stderr,"errore in lettura");
i++;
}
printf("command is %s\n",message);
if (strncmp(message,"QUIT",4)==0){
fprintf(stdout,"QUIT COMMAND RECEIVED");
close(accepted_socket);
}
else{
if(strncmp(message,"GET",3)==0){
// fornire file
printf("GET received\n");
sscanf(message,"%s %s",tmp,filename);
filename[strlen(filename)]='\0';
printf("filename is %s\n",filename);
if((fd=open(filename,O_RDONLY))<0){
//file not found
fprintf(stdout,"file not found");
//send error message
close(accepted_socket);
}
else{ //filefound
printf("file opened file_descriptor %d filename %s\n", fd,filename);
stat(filename,&buff);
printf("stat done %d\n",buff.st_size);
sprintf(message,"+OK\n%d",(buff.st_size));//modificare il \n in spazio x provare
printf("message is:%s",message);
//send confirm and filesize
writen(accepted_socket,message,sizeof(message));
//sendfile
i=0;
printf("start to send file\n");
if(sendfile(accepted_socket,fd,0,buff.st_size)==-1){
i++;
fprintf(stderr,"%s",strerror(errno));
fprintf(stderr,"errore durante sendfile");
//manage error
}
else fprintf(stderr,"file sended");
}
}
else{
fprintf(stdout,"command is wrong\n");
//send error message
sprintf(message,"-ERR\n");
writen(accepted_socket,message,sizeof(message));
}
}
}
int writen(int s, char *ptr, size_t nbytes)
{
size_t nleft;
ssize_t nwritten;
for (nleft=nbytes; nleft > 0; )
{
nwritten = send(s, ptr, nleft, 0);
if (nwritten <=0)
return (nwritten);
else
{
nleft -= nwritten;
ptr += nwritten;
}
}
return (nbytes - nleft);
}
/* Reads a line from stream socket s to buffer ptr
The line is stored in ptr including the final '\n'
At most maxlen chasracters are read
return value:
the number of readed character
-1 if a error occurred
0 with *ptr=0 if the connection is closed by party
*/
int readline (int s, char *ptr, size_t maxlen)
{
size_t n;
ssize_t nread;
char c;
for (n=1; n<maxlen; n++)
{
nread=recv(s, &c, 1, 0);
if (nread == 1)
{
*ptr++ = c;
if (c == '\n')
break;
}
else if (nread == 0) /* connection closed by party */
{
*ptr = 0;
return (n-1);
}
else /* error */
return (-1);
}
*ptr = 0;
return (n);
}
ho scelto di utilizzare la funzione sendfile invece di aprire il file in questione leggerlo e inviare quanto letto per tentare di migliorare le prestazioni....tuttavia non trovando nessuna receivefile ho utilizzato la sendfile anche per ricevere il file (nel client) ma mi viene sempre restituito errore e settato errno a EINVAL ( argomento non valido) l'unica cosa che posso fare è ricevere il file con sequenze di read\write?
grazie a tutti per l'attenzione e l'aiuto
il client (tramite riga di comando) possa richiedere al server un file tramite il comando GET nomefile (seguito da \n)
quando "finito" di richiedere files tramite ll comanod QUIT il client lo segnali al server e chiuda la connessione
il server una volta ricevuto un comando deve verificarne la correttezza (QUIT o GET) dopo di che se il file esiste inviarlo al client e restare in attesa per ulteriori richieste
in caso di errore (file nn esistente/ comando errato) segnalare errore e chiudere la connessione.
testo:
Sviluppare un server TCP (in ascolto sulla porta specificata come primo parametro sulla riga di
comando) che accetti richieste di trasferimento file da client ed invii il file richiesto.
Sviluppare un client che si colleghi ad un server TCP (all’indirizzo e porta specificati come primo e
secondo parametro sulla riga di comando) per richiedere dei file e memorizzarli localmente. I nomi
dei file da richiedere vengono forniti su standard input, uno per riga. Ogni file richiesto deve essere
salvato localmente e deve essere fornito su standard output un messaggio circa l’avvenuto
trasferimento, con nome e dimensione del file.
Per richiedere un file il client invia al server i tre caratteri ASCII “GET” seguiti dal nome del file
(max 64 caratteri) e da CR LF (senza alcun spazio):
GET nomefile CR LF
Il server risponde inviando:
+OK CR LF
seguito dal numero di byte (intero su 32 bit in formato di rete) e quindi dai byte del file in oggetto.
Il client può richiedere più file inviando più comandi GET. Quando intende terminare la
comunicazione invia:
QUIT CR LF
e chiude il canale.
In caso di errore (es. comando illegale, file inesistente) il server risponde sempre con
-ERR CR LF
e quindi chiude il canale col client.
Provare a collegare il proprio client col server sviluppato da un altro gruppo e viceversa.
Mentre è in corso un collegamento provare ad attivare un secondo client verso il medesimo server.
Provare ad attivare sul medesimo nodo una seconda istanza del server sulla medesima porta.
Provare a collegare il client ad un indirizzo non raggiungibile.
Provare a collegare il client ad un indirizzo esistente ma ad una porta su cui il server non è in
ascolto.
Provare a disattivare il server (battendo ^C nella sua finestra) mentre un client è collegato.
CLIENT
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <unistd.h>
#include <error.h>
#include <errno.h>
//define
#define MAXLENFILENAME 64
#define MAXLENMESSAGE MAXLENFILENAME+3+1+2 // filename+ get + \0+\r\n
#define MAXLENREPLY 15
#define ATTEMPT 5 //tentativi
//function prototipie
int writen(int s, char *, size_t maxlen);
int readline (int s, char *ptr, size_t maxlen);
int connectionOpen(int s);
int ConnectSocket(int socket,struct sockaddr_in targetaddress);
int main (int argc, char **argv){
int client_socket=-2; /*socket */
struct sockaddr_in servaddr; /* server address structure */
struct in_addr ipaddress; // server ipaddress
int i;
char command[MAXLENMESSAGE];
char reply[MAXLENREPLY],tmp[MAXLENREPLY];
int reply_dim,fd;
char filename[MAXLENFILENAME];
uint32_t file_size;
int res;
//asd
// check imput parametre
if(argc !=3){
fprintf(stderr,"usage: %s server_addresss port_num",argv[0]);
exit(1);
}
// socket creation
i=0;
do{
client_socket=socket(AF_INET, SOCK_STREAM,IPPROTO_TCP); //AF_INET internet SOCK_STREAM TCP
printf("tentativo %d socket: %d\n",i,client_socket);
i++;
// manage error loocking errno
} while(!client_socket||i==ATTEMPT);
if((i==ATTEMPT)&&(client_socket==0)){
fprintf(stderr,"impossibile create the socket");
exit(1);
}
//server address creation
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&ipaddress);
servaddr.sin_addr=ipaddress;
// connect the socket
if((res=ConnectSocket(client_socket,servaddr))!=0){
fprintf(stderr,"is impossible to connect res:%d\n",res);
exit(1);
}
do{
if((connectionOpen(client_socket))==-1){ // se server chiuso connessione la riapro
if(ConnectSocket(client_socket,servaddr)!=0){
perror("is impossible to connect\n");
}
}
printf("insert a command: GET filename or QUIT to exit\n");
fgets(command,MAXLENMESSAGE,stdin);
fprintf(stdout,"\n\ncommand is: %s\n",command);
//printf("editing command \n");
//strcat(command,"\n");
//printf("edited command is %s\n",command);
writen(client_socket,command,sizeof(command));
if(strncmp(command,"QUIT",4)!=0 ){ // wait the reply from the server and do consequently
sscanf(command,"%s%s",tmp,filename);
sleep(1);
reply_dim=readline(client_socket,reply,sizeof(reply));
reply[reply_dim-1]='\0';//++?
fprintf(stdout,"%s",reply);
char filesize_s[10];
readline(client_socket,filesize_s,sizeof(filesize_s));
fprintf(stdout,"%s",filesize_s);
file_size=atoi(filesize_s);
fprintf(stdout,"%s size is:",filename,file_size);
if(reply[0]=='-'){//error keyword or file not present
fprintf(stderr,"the server reply with error code\n");
close(client_socket);
}
else{ // file presente
//sscanf(reply,"%s%d",tmp,&file_size);
//file_size=(file_size);
//ora devo ricevere il file
printf("filename %s file_size %d\n",filename,file_size);
fd=creat(filename,S_IWRITE);
printf("file created\n");
if((res=sendfile(fd,client_socket,0,file_size))==-1){ // modificare con dimensione letta=dimensione file
printf("error during trasfer file try again\n");
fprintf(stderr,"%s",strerror(errno));
unlink(filename);
}
else{
printf("the transfer of %s is completed\n",filename);
}
close(fd);
}
}
else{// comando=QUIT
close(client_socket);
}
}
while(strcmp(command,"QUIT"));
}
//this function return 0 if the connection is open 1 otherwise
int connectionOpen(int s){
int error = 0;
socklen_t len = sizeof (error);
int retval = getsockopt (s, SOL_SOCKET, SO_ERROR, &error, &len );
if (retval==0)
return 0;
else return -1;
}
// this function connect the socket end return the value
int ConnectSocket(int socket,struct sockaddr_in targetaddress){
int i=0;
int result;
while((i==ATTEMPT)||(result=(connect(socket,(struct sockaddr *)&targetaddress,sizeof(targetaddress)))!=0)){ //try ATTEMPT times to connect
i++;
// manage error loocking errno
}
return result;
}
int writen(int s, char *ptr, size_t nbytes)
{
size_t nleft;
ssize_t nwritten;
for (nleft=nbytes; nleft > 0; )
{
nwritten = send(s, ptr, nleft, 0);
if (nwritten <=0)
return (nwritten);
else
{
nleft -= nwritten;
ptr += nwritten;
}
}
return (nbytes - nleft);
}
/* Reads a line from stream socket s to buffer ptr
The line is stored in ptr including the final '\n'
At most maxlen chasracters are read
return value:
the number of readed character
-1 if a error occurred
0 with *ptr=0 if the connection is closed by party
*/
int readline (int s, char *ptr, size_t maxlen)
{
size_t n;
ssize_t nread;
char c;
for (n=1; n<maxlen; n++)
{
nread=recv(s, &c, 1, 0);
if (nread == 1)
{
*ptr++ = c;
if (c == '\n')
break;
}
else if (nread == 0) /* connection closed by party */
{
*ptr = 0;
return (n-1);
}
else /* error */
return (-1);
}
*ptr = 0;
return (n);
}
SERVER
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <error.h>
//define
#define MAXLENFILENAME 64
#define MAXLENMESSAGE MAXLENFILENAME+3+1+2 // filename+ get + \0+\r\n
#define MAXLENREPLY 15
#define QUEQUEDIM 5
#define ATTEMPT 5 //tentativi
//function prototipie
int writen(int s, char *, size_t maxlen);
int readline (int s, char *ptr, size_t maxlen);
//int connectionOpen(int s);
int main(int argc ,char **argv){
int server_socket,accepted_socket;
int fd;
int i,res;
struct sockaddr_in addr;
struct sockaddr addr_a;
struct stat buff;
socklen_t addr_len_a;
char message[MAXLENMESSAGE],filename[MAXLENFILENAME],tmp[MAXLENMESSAGE];
if(argc!=2){
fprintf(stderr,"using %s port_number",argv[0]);
exit(-1);
}
//creare socket
i=0;
do{
server_socket=socket(AF_INET, SOCK_STREAM,IPPROTO_TCP); //AF_INET internet SOCK_STREAM TCP
printf("tentativo %d socket: %d\n",i,server_socket);
i++;
// manage error loocking errno
} while(!server_socket||i==ATTEMPT);
if((i==ATTEMPT)&&(server_socket==0)){
perror("impossibile create the socket");
}
// address for bind creation
addr.sin_family = AF_INET;
addr.sin_port = htons(atoi(argv[1]));
addr.sin_addr.s_addr= htonl (INADDR_ANY);
//bind
i=0;
do{
res=bind(server_socket,(struct sockaddr*)&addr,sizeof(addr));
// manage error
fprintf(stderr,"errore bind %d error: %d \n",res,errno);
i++;
}
while((res!=0||i==ATTEMPT));
printf("bind result %d\n",res);
//attesa connessione and accettare connessione
i=0;
while((res=listen(server_socket,QUEQUEDIM))!=0||i==ATTEMPT){
fprintf(stderr,"errore durante la listen res: %d i:%d\n",res,i);
i++;
}
i=0;
printf("listen completed %d \n",res);
while( (accepted_socket=accept(server_socket,&addr_a,&addr_len_a))<0||(i==ATTEMPT)){//accept ritorna int>0 (socket descriptor)
fprintf(stderr,"errore durante la accept return value %d i:%d\n",accepted_socket,i);
i++;
}
printf("tentativi accept terminati\n");
if((i==ATTEMPT)&&(res==-1)){
fprintf(stderr,"impossible accept connection\n");
exit(1);
}
//ricevere richiesta
printf("accept eseguita\n");
res=0;
i++;
while(((res=readline(accepted_socket,message,MAXLENMESSAGE))<0)||(i==ATTEMPT)){
fprintf(stderr,"errore in lettura");
i++;
}
printf("command is %s\n",message);
if (strncmp(message,"QUIT",4)==0){
fprintf(stdout,"QUIT COMMAND RECEIVED");
close(accepted_socket);
}
else{
if(strncmp(message,"GET",3)==0){
// fornire file
printf("GET received\n");
sscanf(message,"%s %s",tmp,filename);
filename[strlen(filename)]='\0';
printf("filename is %s\n",filename);
if((fd=open(filename,O_RDONLY))<0){
//file not found
fprintf(stdout,"file not found");
//send error message
close(accepted_socket);
}
else{ //filefound
printf("file opened file_descriptor %d filename %s\n", fd,filename);
stat(filename,&buff);
printf("stat done %d\n",buff.st_size);
sprintf(message,"+OK\n%d",(buff.st_size));//modificare il \n in spazio x provare
printf("message is:%s",message);
//send confirm and filesize
writen(accepted_socket,message,sizeof(message));
//sendfile
i=0;
printf("start to send file\n");
if(sendfile(accepted_socket,fd,0,buff.st_size)==-1){
i++;
fprintf(stderr,"%s",strerror(errno));
fprintf(stderr,"errore durante sendfile");
//manage error
}
else fprintf(stderr,"file sended");
}
}
else{
fprintf(stdout,"command is wrong\n");
//send error message
sprintf(message,"-ERR\n");
writen(accepted_socket,message,sizeof(message));
}
}
}
int writen(int s, char *ptr, size_t nbytes)
{
size_t nleft;
ssize_t nwritten;
for (nleft=nbytes; nleft > 0; )
{
nwritten = send(s, ptr, nleft, 0);
if (nwritten <=0)
return (nwritten);
else
{
nleft -= nwritten;
ptr += nwritten;
}
}
return (nbytes - nleft);
}
/* Reads a line from stream socket s to buffer ptr
The line is stored in ptr including the final '\n'
At most maxlen chasracters are read
return value:
the number of readed character
-1 if a error occurred
0 with *ptr=0 if the connection is closed by party
*/
int readline (int s, char *ptr, size_t maxlen)
{
size_t n;
ssize_t nread;
char c;
for (n=1; n<maxlen; n++)
{
nread=recv(s, &c, 1, 0);
if (nread == 1)
{
*ptr++ = c;
if (c == '\n')
break;
}
else if (nread == 0) /* connection closed by party */
{
*ptr = 0;
return (n-1);
}
else /* error */
return (-1);
}
*ptr = 0;
return (n);
}
ho scelto di utilizzare la funzione sendfile invece di aprire il file in questione leggerlo e inviare quanto letto per tentare di migliorare le prestazioni....tuttavia non trovando nessuna receivefile ho utilizzato la sendfile anche per ricevere il file (nel client) ma mi viene sempre restituito errore e settato errno a EINVAL ( argomento non valido) l'unica cosa che posso fare è ricevere il file con sequenze di read\write?
grazie a tutti per l'attenzione e l'aiuto