Torna indietro   Hardware Upgrade Forum > Software > Programmazione

ASUS NUC 15 Pro e NUC 15 Pro+, mini PC che fondono completezza e duttilità
ASUS NUC 15 Pro e NUC 15 Pro+, mini PC che fondono completezza e duttilità
NUC 15 Pro e NUC 15 Pro+ sono i due nuovi mini-PC di casa ASUS pensati per uffici e piccole medie imprese. Compatti, potenti e pieni di porte per la massima flessibilità, le due proposte rispondono in pieno alle esigenze attuali e future grazie a una CPU con grafica integrata, accompagnata da una NPU per la gestione di alcuni compiti AI in locale.
Cybersecurity: email, utenti e agenti IA, la nuova visione di Proofpoint
Cybersecurity: email, utenti e agenti IA, la nuova visione di Proofpoint
Dal palco di Proofpoint Protect 2025 emerge la strategia per estendere la protezione dagli utenti agli agenti IA con il lancio di Satori Agents, nuove soluzioni di governance dei dati e partnership rafforzate che ridisegnano il panorama della cybersecurity
Hisense A85N: il ritorno all’OLED è convincente e alla portata di tutti
Hisense A85N: il ritorno all’OLED è convincente e alla portata di tutti
Dopo alcuni anni di assenza dai cataloghi dei suoi televisori, Hisense riporta sul mercato una proposta OLED che punta tutto sul rapporto qualità prezzo. Hisense 55A85N è un televisore completo e versatile che riesce a convincere anche senza raggiungere le vette di televisori di altra fascia (e altro prezzo)
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 29-04-2013, 14:01   #1
JcBobo
Member
 
Iscritto dal: Jul 2011
Messaggi: 126
[c\unix]

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:
Quote:
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
Quote:
#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
Quote:
#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

Ultima modifica di JcBobo : 29-04-2013 alle 14:07. Motivo: inserire testo
JcBobo è offline   Rispondi citando il messaggio o parte di esso
Old 29-04-2013, 14:58   #2
airon
Senior Member
 
Iscritto dal: Feb 2004
Città: milano
Messaggi: 2148
Scusa ma come pretendi che si possa leggere qualcosa da un sendfile()?

Sul client usa la recv() o la read() e sei a posto.

Ciao
airon è offline   Rispondi citando il messaggio o parte di esso
Old 29-04-2013, 15:02   #3
JcBobo
Member
 
Iscritto dal: Jul 2011
Messaggi: 126
semplicemente leggendo dati da uno filedescriptor e mandandoli a un altro pensavo che invertendoli (cioè mettendo come in il socket e out il file) funzionasse :P modifico grazie mille

non c'è qlc cosa che si occupi "direttamente" di ricevere i dati e di scriverli sul file (Tipo sendfile per mandarli)

Ultima modifica di JcBobo : 29-04-2013 alle 15:10.
JcBobo è offline   Rispondi citando il messaggio o parte di esso
Old 29-04-2013, 15:13   #4
airon
Senior Member
 
Iscritto dal: Feb 2004
Città: milano
Messaggi: 2148
Eh no. Devi prima leggere dal socket e poi scrivi sul file
E' l'unica.
airon è offline   Rispondi citando il messaggio o parte di esso
Old 29-04-2013, 15:20   #5
airon
Senior Member
 
Iscritto dal: Feb 2004
Città: milano
Messaggi: 2148
In realtà ci sarebbe un altro metodo ma non so se sia il caso, non credo che ve lo abbiano spiegato. Su linux potresti ottimizzare il tutto usando:

pipe(), splice() e tee()


Ah non capisco perchè hai reinventato la ruote con quelle readline e writen
airon è offline   Rispondi citando il messaggio o parte di esso
Old 29-04-2013, 15:43   #6
JcBobo
Member
 
Iscritto dal: Jul 2011
Messaggi: 126
Quote:
Originariamente inviato da airon Guarda i messaggi
In realtà ci sarebbe un altro metodo ma non so se sia il caso, non credo che ve lo abbiano spiegato. Su linux potresti ottimizzare il tutto usando:

pipe(), splice() e tee()


Ah non capisco perchè hai reinventato la ruote con quelle readline e writen
xke piacciono al professore XD (e ho fatto copia incolla da un suo vecchio progetto)

il corso di programmazione distribuita cerca di usare il piu possibile le API "socket" invece che system call o metodi (Secondo me) piu efficaci privilegiando la potabilità alle prestazioni (piu che altro penso per non specializzarsi in un sistema operativo in particolare) ma piu che altro per esercizio sto cercando di realizzare i laboratori in modo piu efficiente possibile per i sistemi operativi a me "noti" (unix e windows).

potresti spiegarmi (anche a grandi linee poi i dettagli implementativi me li guardo io) questo metodo? (non ho mai usato splice e tee e pipe solo un paio d volte in esercizi strutturati apposta come esempio quindi si capisce poco la loro effettiva "potenza") grazie mille



p.s. in realtà il professore usa questa assunzione: se siete in grado di creare un server (parte dell'esame è creare un server) completamente portable (so) implica che sappiate programmare su "tutti" i sistemi operativi (io penso abbia piu senso creare un set di librerie che a seconda della presenza o meno di alcune variabili di sistema sfruttino alcune system call invece di altre a seconda del sistema operativo utilizzato)

Ultima modifica di JcBobo : 29-04-2013 alle 15:45.
JcBobo è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


ASUS NUC 15 Pro e NUC 15 Pro+, mini PC che fondono completezza e duttilità ASUS NUC 15 Pro e NUC 15 Pro+, mini PC che fondo...
Cybersecurity: email, utenti e agenti IA, la nuova visione di Proofpoint Cybersecurity: email, utenti e agenti IA, la nuo...
Hisense A85N: il ritorno all’OLED è convincente e alla portata di tutti Hisense A85N: il ritorno all’OLED è convi...
Recensione Borderlands 4, tra divertimento e problemi tecnici Recensione Borderlands 4, tra divertimento e pro...
TCL NXTPAPER 60 Ultra: lo smartphone che trasforma la lettura da digitale a naturale TCL NXTPAPER 60 Ultra: lo smartphone che trasfor...
Spotify rivoluziona la sua guida: Daniel...
Sora 2: la seconda generazione del model...
Nuovo obiettivo FE 100mm F2.8 Macro GM O...
Steelseries Arctis Nova Elite: le prime ...
30 anni di PlayStation da indossare: arr...
Amazon lancia gli Echo più potent...
Amazon rinnova la gamma Fire TV: ecco le...
Ring lancia le sue prime videocamere con...
Blink amplia la gamma di videocamere di ...
Jaguar Land Rover riprende (gradualmente...
HONOR inaugura il primo ALPHA Flagship S...
Yamaha: ecco il brevetto del 'finto moto...
'Console obsoleta e utenti ingannati': u...
Stop al ransomware su Google Drive, graz...
L'IA è la nuova interfaccia utent...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 00:50.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Served by www3v