Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Wind Tre 'accende' il 5G Standalone in Italia: si apre una nuova era basata sui servizi
Wind Tre 'accende' il 5G Standalone in Italia: si apre una nuova era basata sui servizi
Con la prima rete 5G Standalone attiva in Italia, WINDTRE compie un passo decisivo verso un modello di connettività intelligente che abilita scenari avanzati per imprese e pubbliche amministrazioni, trasformando la rete da infrastruttura a piattaforma per servizi a valore aggiunto
OPPO Find X9 Pro: il camera phone con teleobiettivo da 200MP e batteria da 7500 mAh
OPPO Find X9 Pro: il camera phone con teleobiettivo da 200MP e batteria da 7500 mAh
OPPO Find X9 Pro punta a diventare uno dei riferimenti assoluti nel segmento dei camera phone di fascia alta. Con un teleobiettivo Hasselblad da 200 MP, una batteria al silicio-carbonio da 7500 mAh e un display da 6,78 pollici con cornici ultra ridotte, il nuovo flagship non teme confronti con la concorrenza, e non solo nel comparto fotografico mobile. La dotazione tecnica include il processore MediaTek Dimensity 9500, certificazione IP69 e un sistema di ricarica rapida a 80W
DJI Romo, il robot aspirapolvere tutto trasparente
DJI Romo, il robot aspirapolvere tutto trasparente
Anche DJI entra nel panorama delle aziende che propongono una soluzione per la pulizia di casa, facendo leva sulla propria esperienza legata alla mappatura degli ambienti e all'evitamento di ostacoli maturata nel mondo dei droni. Romo è un robot preciso ed efficace, dal design decisamente originale e unico ma che richiede per questo un costo d'acquisto molto elevato
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 05-07-2014, 14:10   #41
WarDuck
Senior Member
 
L'Avatar di WarDuck
 
Iscritto dal: May 2001
Messaggi: 12861
Ah ecco, effettivamente bisognava essere molto pedantici .

A questo punto la cosa migliore è come dice van:

Codice:
struct message_h
{
    ...
    char message[];
};
Se C99 non è un opzione, allora dico io butta il compilatore o l'ambiente in cui stai sviluppando .
WarDuck è offline   Rispondi citando il messaggio o parte di esso
Old 06-07-2014, 11:12   #42
Daniels118
Senior Member
 
L'Avatar di Daniels118
 
Iscritto dal: Jan 2014
Messaggi: 852
Quote:
Originariamente inviato da WarDuck Guarda i messaggi
Ah ecco, effettivamente bisognava essere molto pedantici .

A questo punto la cosa migliore è come dice van:

Codice:
struct message_h
{
    ...
    char message[];
};
Se C99 non è un opzione, allora dico io butta il compilatore o l'ambiente in cui stai sviluppando .
Premesso che sono assolutamente contrario sia ai "dialetti" dei linguaggi, che alla trasmissione di struct sul socket che lasciano spazio alle interpretazioni (leggasi endianness & co.), scrivendo "char message[];" non si definisce un array nella struttura, ma un puntatore ad un array da allocare che risiederà da qualche parte in memoria, per cui scrivere la struttura sul socket non invierebbe il messaggio ma un puntatore, che ovviamente perde di significato nel momento in cui viene trasmesso sulla rete.
In altre parole "char message[];" è esattamente equivalente a "char *message;", ed è assolutamente diverso da "char message[0];". Ma ribadisco che non mi piace in alcun caso.
Daniels118 è offline   Rispondi citando il messaggio o parte di esso
Old 06-07-2014, 12:10   #43
aeroxr1
Senior Member
 
Iscritto dal: Mar 2006
Messaggi: 2056
Nuovo dubbietto

Sto facendo la recv modificata per gestire la situazione recv==0 cioè la chiusura di una connessione aspettata o inaspettata , e recv<length .

In questo caso pensavo di segnare il ritorno della recv in una variabile per riniziare da lì quando arrivano i rimanenti dati, una cosa del genere :

il client fa send(strlen(dati));
il server :
char *buffer;
buffer=malloc(length*sizeof(char));

recvmod()
{
ret=recv(...)
alla recv dopo
inizio a scrivere da buffer[ret]
}

e questo con i dati che arrivano sotto forma di stringa.

Quando deve arrivare la lunghezza dei dati però li mi nasce il problema, perchè non mi viene in mente un metodo per ricevere un campo int bufferizzandolo.. lo dovrei fare shiftando i dati della quantità ricevuta e facendo poi dopo la or ?
(ora per ora faccio in maniera che la lunghezza length non sia mai superiore ad un byte)
aeroxr1 è offline   Rispondi citando il messaggio o parte di esso
Old 06-07-2014, 12:42   #44
Mettiu_
Member
 
L'Avatar di Mettiu_
 
Iscritto dal: Jul 2011
Messaggi: 246
Mi inserisco tardi in questa discussione, per cui non sono sicuro di aver capito il tuo dubbio...
Per inviare un intero a dimensione fissa (esempio un intero senza segno a 32 bit) puoi fare qualcosa del genere:

Codice:
uint32_t size = 123465; // l'intero che vuoi inviare
size = htonl(size);  // conversione in formato network
send (sock, &size, sizeof(size), 0);
Lato ricevente invece:
Codice:
uint32_t size;
recv(sock, &size, sizeof(size), 0);  // ricevo esattamente quattro bytes
size = ntohl (size);  // conversione
NON dimenticare l'uso di ntohl e htonl (come già suggerito da altri) altrimenti l'endianess può portarti ad interpretare male i bytes che ricevi. Ovviamente finchè fai prove su localhost il problema non si vede
__________________
Non c'è cosa peggiore nella vita di un programmatore di un errore che si presenta solo ogni tanto.

CONCLUSO POSITIVAMENTE CON: oldfield

Ultima modifica di Mettiu_ : 06-07-2014 alle 12:45.
Mettiu_ è offline   Rispondi citando il messaggio o parte di esso
Old 06-07-2014, 13:16   #45
aeroxr1
Senior Member
 
Iscritto dal: Mar 2006
Messaggi: 2056
Quote:
Originariamente inviato da Mettiu_ Guarda i messaggi
Mi inserisco tardi in questa discussione, per cui non sono sicuro di aver capito il tuo dubbio...
Per inviare un intero a dimensione fissa (esempio un intero senza segno a 32 bit) puoi fare qualcosa del genere:

Codice:
uint32_t size = 123465; // l'intero che vuoi inviare
size = htonl(size);  // conversione in formato network
send (sock, &size, sizeof(size), 0);
Lato ricevente invece:
Codice:
uint32_t size;
recv(sock, &size, sizeof(size), 0);  // ricevo esattamente quattro bytes
size = ntohl (size);  // conversione
NON dimenticare l'uso di ntohl e htonl (come già suggerito da altri) altrimenti l'endianess può portarti ad interpretare male i bytes che ricevi. Ovviamente finchè fai prove su localhost il problema non si vede
Ciao e grazie per l'aiuto
Il mio dubbio viene dal fatto che la recv ci sta non riceva tutti i byte insieme. Quindi considerando i 32 bit dell'int , se ricevo solo i primi 8 bit , cioè solo il primo byte avrei un errore no ?
Quindi non mi servirebbe un sistema di bufferizzazione anche per l'int ?

(prima di iniziare questa discussione non pensavo ci fossero di questi problemi e la ricezione la facevo anche io ricevendo la size dell'int )

Questa è la struttura che ho creato :

Codice:
struct elemento 
{ 
	char *username; //Username del giocatore , crerò dinamicamente lo spazio in maniera di non sprecare memoria
	short int UDPports;
	unsigned long IPaddress;
	int socket; //id del socket
	char ready; //indica se il client ha effettuato il login o è sempre in attesa di login e quindi non ancora connesso
	char impegnato; //mi indicherà Se il client è impegnato in un'altra partita
	
	char cmd ; //il comando che stiamo eseguendo. Inizialmente in waiting !
	int stato; //variabile di stato che mi dice in che parte della macchina a stati si trova il client
	int length; //lunghezza campo dati
	char *buffer; //buffer dove vengono ricevuti i dati temporaneamente prima di essere ricevuti completamente, buffer dinamico
	int last; //variabile che indica fino a che punto abbiamo riempito il buffer in caso di lettura non terminata
	
	struct elemento *next; //puntatore all'elemento successivo della lista
	struct elemento *enemy; //puntatore alla struttura dell'avversario
};

typedef struct elemento player;
queste le funzioni di ricezione :

Codice:
int recvTCP(int sd, void* buf, int len)  // possibile implementazione
{
	int ret;
	ret = recv(sd,buf,len,0);
	if (ret<len)
	{
		if(ret==0)  //chiusura connessione da parte di un client oppure errore
		{
			//chiusura connessione da parte di un client oppure errore
		 	close(sd); //chiudo la socket
		 	FD_CLR(sd,&master); //rimuovo la socket dal master set
		 	printf("%s si è disconnesso dal server",client->username);
		 	if(client->impegnato==YES)  //si è chiuso durante una partita quindi è un problema da notificare all'avversario
		 	{
		 		//notifica(client->enemy->socket);
		 	}
		 	elem_remove(client,&connessi); //rimuove l'elemento dalla lista connessi
		 	return -1; //non ritorna nessun byte c'è solo stata una chiusura
		}
		//qui ci vorrebbe un buffer da riempire fino a quando sono disponibili tutti i dati, cosa faccio ?
		//chiedere al professore
		return ret; //ritorna il numero di byte letti 
		
	}
	return 0; // tutto ok
}

void riceviLength() //creato una funzione separata per la futura gestione del buffer della lunghezza
{
  recvTCP(client->socket,&(client->length),sizeof(int)); //dato che ricevo un solo byte forse //è meglio metta 1 al posto di sizeof(int)
}

int riceviMsg()
{
	int ret;
	ret = recvTCP(client->socket,&(client->buffer[client->last]),client->length);
	if(ret<0) return -1; //c'è stata una chiusura della connessione
	if(ret==0) 
	{
		client->last=0; //rimetto a 0 la variabile che mi indica dove sono rimasto a leggere
		return 0; //dato completamente ricevuto
	}
	client->last=ret;
	client->length=(client->length)-(client->last);  //aggiorno la lunghezza da leggere all'interno della struttura client
	return ret;
}
VIene compilato senza errori, ma non l'ho provato, perchè mi manca ancora una gestione dei comandi da applicare. Però non so se ho commesso qualche errore di logica nel codice qui sopra

Ultima modifica di aeroxr1 : 06-07-2014 alle 13:19.
aeroxr1 è offline   Rispondi citando il messaggio o parte di esso
Old 07-07-2014, 07:14   #46
Daniels118
Senior Member
 
L'Avatar di Daniels118
 
Iscritto dal: Jan 2014
Messaggi: 852
Quote:
Quando deve arrivare la lunghezza dei dati però li mi nasce il problema, perchè non mi viene in mente un metodo per ricevere un campo int bufferizzandolo.. lo dovrei fare shiftando i dati della quantità ricevuta e facendo poi dopo la or ?
Ricordati che la recv non ritorna il dato letto, ma devi passare in input un puntatore ad un buffer. Io personalmente farei così:
Codice:
char buf[4];
int n = 0;
while (n < 4) {
  n += recv(sockfd, &buf[n], 4 - n, 0);
}
oppure così:
Codice:
char buf[4];
while (recv(sockfd, buf, 4, MSG_PEEK) < 4) {}
recv(sockfd, buf, 4, 0);
e poi usi shift e or per ricostruire il numero.
Ovviamente sul server il ciclo va gestito diversamente con la select, inoltre vanno gestiti gli errori.
Dei due metodi il primo è da preferire, soprattutto nel caso di dati corposi.
Daniels118 è offline   Rispondi citando il messaggio o parte di esso
Old 07-07-2014, 09:35   #47
aeroxr1
Senior Member
 
Iscritto dal: Mar 2006
Messaggi: 2056
Quote:
Originariamente inviato da Daniels118 Guarda i messaggi
Ricordati che la recv non ritorna il dato letto, ma devi passare in input un puntatore ad un buffer. Io personalmente farei così:
Codice:
char buf[4];
int n = 0;
while (n < 4) {
  n += recv(sockfd, &buf[n], 4 - n, 0);
}
oppure così:
Codice:
char buf[4];
while (recv(sockfd, buf, 4, MSG_PEEK) < 4) {}
recv(sockfd, buf, 4, 0);
e poi usi shift e or per ricostruire il numero.
Ovviamente sul server il ciclo va gestito diversamente con la select, inoltre vanno gestiti gli errori.
Dei due metodi il primo è da preferire, soprattutto nel caso di dati corposi.
Grazie
Quei cicli li posso fare sul client , sul server li dovrò spezzettare tutti
Certo era tanto semplice se la select segnalava solo i socket pronti con il numero di byte voluti

Per il passaggio da int a string itoa() ha problemi di portabilità che voi sappiate ?


p.s : ora provo il codice che ho postato ieri, però lo provo in locale mettendo server e client sulla stessa macchina quindi sarà difficile vedere se ho strutturato bene i cicli per il buffer della recv
aeroxr1 è offline   Rispondi citando il messaggio o parte di esso
Old 07-07-2014, 09:47   #48
Daniels118
Senior Member
 
L'Avatar di Daniels118
 
Iscritto dal: Jan 2014
Messaggi: 852
Itoa converte un int in una stringa in formato decimale, di lunghezza variabile. Ti conviene utilizzare sprintf se vuoi trasmettere in formato decimale di lunghezza fissa, oppure utilizzare shift e and per prendere i byte uno alla volta.
Daniels118 è offline   Rispondi citando il messaggio o parte di esso
Old 07-07-2014, 09:52   #49
aeroxr1
Senior Member
 
Iscritto dal: Mar 2006
Messaggi: 2056
Quote:
Originariamente inviato da Daniels118 Guarda i messaggi
Itoa converte un int in una stringa in formato decimale, di lunghezza variabile. Ti conviene utilizzare sprintf se vuoi trasmettere in formato decimale di lunghezza fissa, oppure utilizzare shift e and per prendere i byte uno alla volta.
Ah ok grazie Intanto per ora cerco di far funzionare il tutto mandando massimo un byte di lunghezza. Quando tutto funzionerà implementerò anche questo buffer D
aeroxr1 è offline   Rispondi citando il messaggio o parte di esso
Old 07-07-2014, 13:11   #50
aeroxr1
Senior Member
 
Iscritto dal: Mar 2006
Messaggi: 2056
Ho deciso di implementare da subito il buffer anche per la lunghezza in maniera da non avere limiti sul buffer del dato

Ecco qua come l'ho scritto, potete dargli un occhiata per vedere se secondo voi è corretto ? Va bè capisco se non ne avrete voglia

Codice:
int recvTCP(int sd, void* buf, int len)  //DUBBIO : Per ora in caso di ritorno < lenght non faccio la chiusura, ma gestisco il buffer !
{
	int ret;
	ret = recv(sd,buf,len,0);
	if (ret<len)
	{
		if(ret==0)  //chiusura connessione da parte di un client oppure errore
		{
			//chiusura connessione da parte di un client oppure errore
		 	close(sd); //chiudo la socket
		 	FD_CLR(sd,&master); //rimuovo la socket dal master set
		 	printf("%s si è disconnesso dal server",client->username);
		 	if(client->impegnato==YES)  //si è chiuso durante una partita quindi è un problema da notificare all'avversario
		 	{
		 		//notifica(client->enemy->socket);
		 	}
		 	elem_remove(client,&connessi); //rimuove l'elemento dalla lista connessi
		 	return -1; //non ritorna nessun byte c'è solo stata una chiusura
		}
		//qui ci vorrebbe un buffer da riempire fino a quando sono disponibili tutti i dati, cosa faccio ?
		//chiedere al professore
		return ret; //ritorna il numero di byte letti 
		
	}
	return 0; // tutto ok
}

int riceviLength() //creato una funzione separata per la futura gestione del buffer della lunghezza
{
   //in realtà inviando un int per la dimensione invio ben 4byte, devo gestire un buffer per la lunghezza
  int ret;
  int temp; //ci viene salvato il dato letto
  ret = recvTCP(client->socket,&temp,sizeof(int));
  temp=(int)ntohl(temp);
  client->last=(client->last)|temp;  
  if(ret<0) return -1; //c'è stata una chiusura della connessione già gestita dalla recvTCP 
  if (ret==0)
  {
  	client->length=client->last; 
  	client->last=0;
  	return 0;
  }
  
  client->last=(client->last)<<(8*(ret)); 
   
  return ret;
}
Grazie di nuovo a tutti

p.s : nelle dispense da cui studio è scritto che anche la send può inviare meno dati di quelli previsti e i dati inviati vengono ritornati dalla funzione. Ora il dubbio è : seguendo quanto dice la dispensa dovrei fare un buffer anche di quella
Sotto TCP se la send() mi ritorna un valore < di quello previsto posso direttamente gestire la chiusura di connessione in quanto c'è stato un errore di connessione ? e sotto UDP ?

Ultima modifica di aeroxr1 : 07-07-2014 alle 15:00.
aeroxr1 è offline   Rispondi citando il messaggio o parte di esso
Old 07-07-2014, 14:41   #51
van9
Member
 
Iscritto dal: Nov 2012
Messaggi: 126
Quote:
Originariamente inviato da WarDuck Guarda i messaggi
Ho provato su Debian 7 con GCC 4.7 e con i flag -Wall -Wextra non riporta nulla (non ho dovuto neanche passargli std C99).

Ora giusto per curiosità provo sulle ultime versioni di clang e Visual Studio 2013 .

Edit: neanche Visual Studio si lamenta (sempre abilitando tutti i Warning), sarà perché usa un compilatore C++.

Edit2: neanche llvm 3.4, sempre passando -Wall -Wextra.

In pratica possiamo buttare tutti i compilatori esistenti .
Naa, mi pagano troppo bene per saperli usare.
van9 è offline   Rispondi citando il messaggio o parte di esso
Old 07-07-2014, 15:24   #52
Mettiu_
Member
 
L'Avatar di Mettiu_
 
Iscritto dal: Jul 2011
Messaggi: 246
Quote:
Originariamente inviato da Daniels118 Guarda i messaggi
Itoa converte un int in una stringa in formato decimale, di lunghezza variabile. Ti conviene utilizzare sprintf se vuoi trasmettere in formato decimale di lunghezza fissa, oppure utilizzare shift e and per prendere i byte uno alla volta.
No, questo approccio ha diversi problemi:
- la lunghezza non va inviata come stringa altrimenti diventa essa stessa variabile. Ad esempio se la lunghezza è 10 io invio la stringa "10" che è lunga due bytes mentre se la lunghezza è 100, invio la stringa "100" che è lunga tre bytes. Fare in modo che questa STRINGA abbia una lunghezza fissa mi sembra un lavoro inutile;
- fare gli shift e gli OR che dite voi (inviando byte per byte) è anche peggio in quanto uno non può semplicemente leggere la memoria byte per byte e inviarne il contenuto perchè poi il ricevente, appena prova a interpretare quei byte come intero, non sa come fare a causa dell'endianess (e il risultato può essere errato).

Un modo possibile (che eviti questi problemi) l'ho già scritto qualche post fa... In aggiunta a quel codice, si può dire che uno può aggiungere un controllo per verificare che recv riceva il numero esatto di bytes (cioè 4 per un uint32). Se l'altro end-point è implementato bene questa condizione deve essere rispettata (l'intero deve essere inviato con una singola chiamata send chiaramente). Altrimenti io chiuderei pure la socket perchè se c'è un protocollo e una delle parti non lo rispetta allora puoi benissimo chiudergli la porta in faccia.
__________________
Non c'è cosa peggiore nella vita di un programmatore di un errore che si presenta solo ogni tanto.

CONCLUSO POSITIVAMENTE CON: oldfield
Mettiu_ è offline   Rispondi citando il messaggio o parte di esso
Old 07-07-2014, 15:29   #53
aeroxr1
Senior Member
 
Iscritto dal: Mar 2006
Messaggi: 2056
Quote:
Originariamente inviato da Mettiu_ Guarda i messaggi
No, questo approccio ha diversi problemi:
- la lunghezza non va inviata come stringa altrimenti diventa essa stessa variabile. Ad esempio se la lunghezza è 10 io invio la stringa "10" che è lunga due bytes mentre se la lunghezza è 100, invio la stringa "100" che è lunga tre bytes. Fare in modo che questa STRINGA abbia una lunghezza fissa mi sembra un lavoro inutile;
- fare gli shift e gli OR che dite voi (inviando byte per byte) è anche peggio in quanto uno non può semplicemente leggere la memoria byte per byte e inviarne il contenuto perchè poi il ricevente, appena prova a interpretare quei byte come intero, non sa come fare a causa dell'endianess (e il risultato può essere errato).

Un modo possibile (che eviti questi problemi) l'ho già scritto qualche post fa... In aggiunta a quel codice, si può dire che uno può aggiungere un controllo per verificare che recv riceva il numero esatto di bytes (cioè 4 per un uint32). Se l'altro end-point è implementato bene questa condizione deve essere rispettata (l'intero deve essere inviato con una singola chiamata send chiaramente). Altrimenti io chiuderei pure la socket perchè se c'è un protocollo e una delle parti non lo rispetta allora puoi benissimo chiudergli la porta in faccia.
ora mi vado a rileggere come avevi detto di fare te

Ma in questa maniera quale sarebbe l'errore ?

Codice:
int riceviLength() //creato una funzione separata per la futura gestione del buffer della lunghezza
{
   //in realtà inviando un int per la dimensione invio ben 4byte, devo gestire un buffer per la lunghezza
  int ret;
  int temp; //ci viene salvato il dato letto
  ret = recvTCP(client->socket,&temp,sizeof(int));
  temp=(int)ntohl(temp);
  client->last=(client->last)|temp;  
  if(ret<0) return -1; //c'è stata una chiusura della connessione già gestita dalla recvTCP 
  if (ret==0)
  {
  	client->length=client->last; 
  	client->last=0;
  	return 0;
  }
  
  client->last=(client->last)<<(8*(ret)); 
   
  return ret;
}
recvTCP è una funzione che ho creato io che ho postato sopra

Te lo chiedo giusto per capire dove sbaglio

ho ritrovato il codice che hai consigliato te:
Quote:
Originariamente inviato da Mettiu_ Guarda i messaggi
Mi inserisco tardi in questa discussione, per cui non sono sicuro di aver capito il tuo dubbio...
Per inviare un intero a dimensione fissa (esempio un intero senza segno a 32 bit) puoi fare qualcosa del genere:

Codice:
uint32_t size = 123465; // l'intero che vuoi inviare
size = htonl(size);  // conversione in formato network
send (sock, &size, sizeof(size), 0);
Lato ricevente invece:
Codice:
uint32_t size;
recv(sock, &size, sizeof(size), 0);  // ricevo esattamente quattro bytes
size = ntohl (size);  // conversione
NON dimenticare l'uso di ntohl e htonl (come già suggerito da altri) altrimenti l'endianess può portarti ad interpretare male i bytes che ricevi. Ovviamente finchè fai prove su localhost il problema non si vede
facendo come dici te la send è fatta in una volta sola come d'altronde faccio anche io
La recv non è detto riceva tutto in una volta sola giusto ?
quindi ci sta benissimo che la length che sta su 4byte viene si inviata intera, ma che alla recv arrivi solo il primo dei 4 byte no ??
In quel caso non devo aspettare mi arrivino gli altri 3 byte ?

Oppure non c'è possibilità che venga spezzettato un int ?

Ultima modifica di aeroxr1 : 07-07-2014 alle 15:43.
aeroxr1 è offline   Rispondi citando il messaggio o parte di esso
Old 07-07-2014, 15:36   #54
Daniels118
Senior Member
 
L'Avatar di Daniels118
 
Iscritto dal: Jan 2014
Messaggi: 852
Quote:
- la lunghezza non va inviata come stringa altrimenti diventa essa stessa variabile. Ad esempio se la lunghezza è 10 io invio la stringa "10" che è lunga due bytes mentre se la lunghezza è 100, invio la stringa "100" che è lunga tre bytes. Fare in modo che questa STRINGA abbia una lunghezza fissa mi sembra un lavoro inutile;
E' proprio per questo che ho consigliato sprintf al posto di itoa, perché utilizzando la stringa di formattazione opportuna è possibile allineare il numero ad una lunghezza fissa, per esempio 10 diventa "00010" e 100 diventa "00100", il numero di caratteri è sempre 5.
Quote:
- fare gli shift e gli OR che dite voi (inviando byte per byte) è anche peggio in quanto uno non può semplicemente leggere la memoria byte per byte e inviarne il contenuto perchè poi il ricevente, appena prova a interpretare quei byte come intero, non sa come fare a causa dell'endianess (e il risultato può essere errato).
Gli shift agiscono sul valore, indipendentemente dall'endiannes del sistema.
Daniels118 è offline   Rispondi citando il messaggio o parte di esso
Old 07-07-2014, 15:45   #55
aeroxr1
Senior Member
 
Iscritto dal: Mar 2006
Messaggi: 2056
@Mettiu_ ho modificato la risposta al tuo post

@Daniels118 quindi se gli shift agiscono sul valore indipendentemente dall'endianess del sistema è inutile il ntohl che ho applicato al mio int prima di fare la shift ?
aeroxr1 è offline   Rispondi citando il messaggio o parte di esso
Old 07-07-2014, 15:53   #56
van9
Member
 
Iscritto dal: Nov 2012
Messaggi: 126
Quote:
Originariamente inviato da Daniels118 Guarda i messaggi
Premesso che sono assolutamente contrario sia ai "dialetti" dei linguaggi, che alla trasmissione di struct sul socket che lasciano spazio alle interpretazioni (leggasi endianness & co.), scrivendo "char message[];" non si definisce un array nella struttura, ma un puntatore ad un array da allocare che risiederà da qualche parte in memoria, per cui scrivere la struttura sul socket non invierebbe il messaggio ma un puntatore, che ovviamente perde di significato nel momento in cui viene trasmesso sulla rete.
In altre parole "char message[];" è esattamente equivalente a "char *message;", ed è assolutamente diverso da "char message[0];". Ma ribadisco che non mi piace in alcun caso.
No. Come dicevo, in C99 "char message[]" come ultimo membro di una struct e quando effettivamente preceduto da (almeno) un altro named member non è un puntatore ma un incomplete array type che prende il nome di "flexible array member". Studialo nello standard.

Il problema dello spedire su socket intere struct si risolve semplicemente non facendolo visto che è sempre e comunque una cattiva idea.

L' "equivalenza" tra array e puntatori non esiste - non sono la stessa cosa. Punto. Sono intercambiabili in alcune circostanze, che è molto diverso. Possibile sia così difficile da capire?

Di "char message[0];" già detto.

Ultima modifica di van9 : 07-07-2014 alle 15:56.
van9 è offline   Rispondi citando il messaggio o parte di esso
Old 07-07-2014, 16:10   #57
Daniels118
Senior Member
 
L'Avatar di Daniels118
 
Iscritto dal: Jan 2014
Messaggi: 852
@van9
Credo che tu ti stia rivolgendo alla persona sbagliata, non sono io a voler trasmettere la struct sul socket.
Daniels118 è offline   Rispondi citando il messaggio o parte di esso
Old 07-07-2014, 16:12   #58
Daniels118
Senior Member
 
L'Avatar di Daniels118
 
Iscritto dal: Jan 2014
Messaggi: 852
Quote:
Originariamente inviato da aeroxr1 Guarda i messaggi
@Mettiu_ ho modificato la risposta al tuo post

@Daniels118 quindi se gli shift agiscono sul valore indipendentemente dall'endianess del sistema è inutile il ntohl che ho applicato al mio int prima di fare la shift ?
Si, se usi gli shift puoi fare a meno di ntohl.
Daniels118 è offline   Rispondi citando il messaggio o parte di esso
Old 07-07-2014, 16:39   #59
Mettiu_
Member
 
L'Avatar di Mettiu_
 
Iscritto dal: Jul 2011
Messaggi: 246
Quote:
Originariamente inviato da aeroxr1 Guarda i messaggi
@Mettiu_ ho modificato la risposta al tuo post
Non c'è ragione per cui l'int possa essere spezzettato se il trasmettitore fà una sola send().

Quote:
Originariamente inviato da aeroxr1 Guarda i messaggi
@Daniels118 quindi se gli shift agiscono sul valore indipendentemente dall'endianess del sistema è inutile il ntohl che ho applicato al mio int prima di fare la shift ?
Vorrei ribadire la regola generale: se il tuo dato copre più bytes (come un uint32, che occupa 4 bytes) allora hai il problema dell'endianess e devi gestire la situazione tramite ntohl et similia. Se il tuo dato occupa solo un byte (come nel caso dei char) non c'è il problema dell'endianess perchè il modo di interpretare quel dato in memoria non cambia su piattaforme con diverso endianess. Per cui per la mia soluzione, valgono le mie considerazioni (devi usare htonl). Per la soluzione di Daniels, valgono le sue. La differenza è dovuta al fatto che lui suggerisce di inviare char, mentre io suggerisco di inviare un uint32.
__________________
Non c'è cosa peggiore nella vita di un programmatore di un errore che si presenta solo ogni tanto.

CONCLUSO POSITIVAMENTE CON: oldfield
Mettiu_ è offline   Rispondi citando il messaggio o parte di esso
Old 07-07-2014, 16:40   #60
van9
Member
 
Iscritto dal: Nov 2012
Messaggi: 126
Quote:
Originariamente inviato da Daniels118 Guarda i messaggi
@van9
Credo che tu ti stia rivolgendo alla persona sbagliata, non sono io a voler trasmettere la struct sul socket.
Ah ok sorry. Il resto del post resta per te, ovviamente.

edit: no aspè mi sto imbrogliando. L'ho capito che tu non sei per la trasmissione diretta. Quello che non ho chiarito è che, utilizzando i flexible members di C99 è vero che si perde la possibilità di copia diretta tra due struct tramite operatore d'assegnamento (non perché si copi un pointer come erroneamente pensi tu ma perché viene copiato un incomplete array). Ma la cosa non ci tange comunque visto che un invio di dati binari su socket come in questo caso e non serializzato a dovere può solo portare problemi, a cominciare dal padding nelle strutture e via dicendo.

Ultima modifica di van9 : 07-07-2014 alle 16:51.
van9 è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Wind Tre 'accende' il 5G Standalone in Italia: si apre una nuova era basata sui servizi Wind Tre 'accende' il 5G Standalone in Italia: s...
OPPO Find X9 Pro: il camera phone con teleobiettivo da 200MP e batteria da 7500 mAh OPPO Find X9 Pro: il camera phone con teleobiett...
DJI Romo, il robot aspirapolvere tutto trasparente DJI Romo, il robot aspirapolvere tutto trasparen...
DJI Osmo Nano: la piccola fotocamera alla prova sul campo DJI Osmo Nano: la piccola fotocamera alla prova ...
FUJIFILM X-T30 III, la nuova mirrorless compatta FUJIFILM X-T30 III, la nuova mirrorless compatta
Google Maps avrà una modalit&agra...
HONOR sta lavorando a uno smartphone con...
Thermaltake MAGFloe 360 Ultra ARGB Sync:...
Xiaomi 15T ora in super offerta su Amazo...
Si stringe il cerchio attorno a TP-Link ...
Amazon cambia i prezzi ancora una volta:...
Imperdibili i Google Pixel 10 a questi p...
Dyson OnTrac in super offerta su Amazon:...
Amazon: la nuova ondata di licenziamenti...
Questo portatile è un mostro: MSI...
Apple Watch Series 11 GPS + Cellular cro...
JBL Clip 5 in forte sconto su Amazon: lo...
Il nuovo top di gamma compatto di OnePlu...
Cresce il divario tra dispositivi elettr...
La missione con equipaggio Shenzhou-21 h...
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: 20:34.


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