|
|
|
|
Strumenti |
07-07-2014, 15:47 | #61 | ||
Senior Member
Iscritto dal: Jan 2014
Messaggi: 852
|
@Mettiu_
Quote:
Quote:
|
||
07-07-2014, 15:56 | #62 | ||
Senior Member
Iscritto dal: Jan 2014
Messaggi: 852
|
Quote:
Quote:
|
||
07-07-2014, 17:01 | #63 |
Senior Member
Iscritto dal: Mar 2006
Messaggi: 2049
|
ma alla fine comunque un ntohl lo devo fare o sbaglio ?
cioè io shifto il valore che ho ricevuto di (8bit*il numero di byte letti) e poi faccio la or con i byte letti al nuovo giro. Ma con questa soluzione ho due dubbi : - ammettendo di aver fatto la procedura corretta alla fine quando ho il dato definitivo devo comunque usare ntohl sulla variabile contenente la lettura finale o sbaglio ? - questo metodo funziona se il primo byte ricevuto è il byte più significativo, non so come mai ma nella mia testa ho dato per scontato funzionasse così, ma è realmente così ? |
09-07-2014, 07:28 | #64 |
Senior Member
Iscritto dal: Jan 2014
Messaggi: 852
|
No, se usi lo shift non c'è bisogno di usare ntohl perché sei tu stesso a controllare l'ordine dei byte.
|
09-07-2014, 08:50 | #65 | |
Senior Member
Iscritto dal: Mar 2006
Messaggi: 2049
|
Quote:
In pseudocodice : lato client : Codice:
send(intero 32bit) Codice:
ret=recv(&temp) poi ad ogni recv farò una cosa del genere : Codice:
rimanenti=4-ret; lunghezza | temp if(ret != rimanenti) //non ho finito di ricevere client->lunghezza<<8*ret (shifto la lunghezza per metterla in posizione di aggiungerci i byte che verranno ricevuti al giro dopo) if (ret==rimanenti) { client-> temp = 0; client->rimanenti = 4; return; } parte più significativa parte meno significativa così il ricevitore riceverà prima la parte più significativa e poi la parte meno significativa. Se lato sender invio in network byte order send(htonl(lunghezza)) quindi con la parte più significativa a destra dovrei ricevere lato ricevitore prima la parte più alta e poi quella più bassa giusto ? Ultima modifica di aeroxr1 : 09-07-2014 alle 08:59. |
|
09-07-2014, 09:12 | #66 | |
Senior Member
Iscritto dal: May 2001
Messaggi: 12582
|
Quote:
Leggo 4, capisco che devo leggere altri 506, leggo 506. Rimangono 2 bytes. Quando chiedo 4 bytes, ovviamente mi devo assicurare che la recv legga 4 bytes, quindi il giusto modo di fare la cosa è fare la recv in un ciclo finché non leggo effettivamente il giusto numero di bytes. Quello che dici non è un problema. |
|
09-07-2014, 09:54 | #67 | |
Senior Member
Iscritto dal: Mar 2006
Messaggi: 2049
|
Quote:
Solo che il mio server deve essere monoprocesso monothread e devo usare la select , ma al tempo stesso non vorrei rimanere in loop per troppo tempo aspettando di aver ricevuto tutti i byte. Per questo mi ha poi consigliato di gestire un buffer Ora il buffer per la stringa dati mi sembra di averlo fatto e teoricamente mi sembra funzioni. Il buffer per la ricezione dell'int della lunghezza del dato invcece mi crea non pochi problemi EDIT [forse così potrebbe funzionare] : Codice:
int riceviLength() //usando lo shift sistemo i byte in host order senza usare la funzione ntohl { //in realtà inviando un int per la dimensione invio ben 4byte, devo gestire un buffer per la lunghezza int ret; int temp; //al suo interno ci viene salvato il dato letto ret = recvTCP(client->socket,&temp,4-client->last); client->length=(client->length)<<(8*(ret)); client->length=(client->length)|temp; if(ret<0) return -1; //c'è stata una chiusura della connessione già gestita dalla recvTCP o il dato è ricevuto correttamente if (ret==0) //abbiamo finito di leggere { client->last=0; return 0; } client->last=client->last-ret; return ret; } Ah recvTCP mi ritorna 0 se ho letto tutto length , -1 se ci sono stati errori , ret se non abbiamo ancora finito di leggere. Ultima modifica di aeroxr1 : 09-07-2014 alle 10:14. |
|
09-07-2014, 13:33 | #68 | |
Senior Member
Iscritto dal: May 2001
Messaggi: 12582
|
Quote:
Se ti aspetti di leggere 4 bytes, dovrai per forza aspettare che arrivino . |
|
09-07-2014, 15:40 | #69 | |
Senior Member
Iscritto dal: Mar 2006
Messaggi: 2049
|
Quote:
3 stati : stato 0 -> attesa comando stato 1 -> attesa lunghezza dati stato 2 -> attesa dato Ogni client ha una struttura e in essa è presente una variabile stato ultimo dato letto e un buffer, e da uno stato a l'altro ci va solo quando ha finito di fare la lettura. Così nel frattempo che il determinato socket non ha i dati disponibile la select riprende il controllo e può gestire le altre connessioni. Mi manca di capire se ho gestito in maniera corretta i buffer. Che in locale è difficile capirlo Ultima modifica di aeroxr1 : 09-07-2014 alle 15:50. |
|
10-07-2014, 19:15 | #70 |
Senior Member
Iscritto dal: Mar 2006
Messaggi: 2049
|
ah scusate , ho una domandina nuova
Se mando una stringa avete detto non c'è problemi di endianess, come mai questa differenza di comportamento ? e una domanda un pò off topic : scanf vs fgets nella lettura dello stdin . se leggo la stringa "pippo" e l'assegno alla variabile stringa usando scanf questa mi lascia \n in memoria e aggiunge l'eof a pippo e quindi in stringa ci sarà "pippo\0" con fgets il buffer stdin mi viene completamente ripulito e viene assegnato a stringa "pippo\n\0" ? corretto ? Quindi in una lettura di un un numero che poi dopo vado a convertire con strtol tutto ok perchè \n non me lo converte , ma se devo leggere una stringa è bene elimini l'ultimo carattere \n o sbaglio ? Come dovrei gestire questa situazione Ultima modifica di aeroxr1 : 10-07-2014 alle 19:56. |
11-07-2014, 13:01 | #71 | |
Senior Member
Iscritto dal: Jan 2014
Messaggi: 852
|
Quote:
Questa differenza di comportamento è nata diversi decenni fa, fondamentalmente per risparmiare sulla realizzazione dei circuiti (non so nello specifico in che modo), ed è stata ereditata dai processori più recenti per mantenere la retrocompatibilità. Anche i compilatori possono impattare sull'endiannes quando lavorano con dati la cui dimensione supera quella dei registri, in questi casi infatti è il compilatore stesso a decidere l'ordine delle "parole" in memoria. |
|
14-07-2014, 08:17 | #72 |
Senior Member
Iscritto dal: Mar 2006
Messaggi: 2049
|
ma quindi se invio la stringa
char pippo[10]={asino/0}; dall'altra parte, dato che invio 6 byte non è detto che arrivi la parola nell'ordine corretto ? |
14-07-2014, 11:49 | #73 | ||
Senior Member
Iscritto dal: Sep 2005
Città: Torino
Messaggi: 606
|
Quote:
Come ti è stato detto, Quote:
__________________
"Se proprio dovete piratare un prodotto, preferiamo che sia il nostro piuttosto che quello di qualcun altro." [Jeff Raikes] "Pirating software? Choose Microsoft!" |
||
14-07-2014, 11:57 | #74 |
Senior Member
Iscritto dal: Jan 2014
Messaggi: 852
|
La risposta di Oceans11 è corretta.
Il motivo è che quando copi una stringa con codifica a byte singolo (per esempio ASCII), l'algoritmo copia i byte uno alla volta, nell'ordine in cui si trovano. Se invece copi una stringa con codifica a 2 byte, l'algoritmo potrebbe copiare i byte due per volta (nel senso che fa un'unica MOVE a 16 bit); l'ordine delle lettere resta invariato, ma l'ordine dei byte di ciascuna lettera potrebbe essere invertito o meno in base all'endiannes. Se hai intenzione di utilizzare codifiche multibyte devi tener conto anche di questo aspetto, altrimenti puoi semplicemente ignorarlo. |
15-07-2014, 08:51 | #75 | |
Senior Member
Iscritto dal: Mar 2006
Messaggi: 2049
|
Quote:
Grazie a tutti |
|
15-07-2014, 16:11 | #76 |
Senior Member
Iscritto dal: Mar 2006
Messaggi: 2049
|
Ho un grosso problema , ma non sapendo bene fare ad usare il debug è difficile che riuscirò a risolverlo
Non capisco come , ma nonostante elimini un elemento dalla lista dei client al passo dopo mi continua a dire che quell'elemento è ancora presente .. boh... Ho trovato dove è l'errore, ma non capisco come mai.... Qualche anima pia , ha due secondi per dare un occhiata al file ? Ecco di seguito : Codice:
struct elemento { char username[256]; //Username del giocatore [max 14 caratteri] short int UDPport; 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[256]; //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; Codice:
player *creatElem(int socket,unsigned long IPaddress) { player *elem = NULL; elem = malloc(sizeof(player)); elem->IPaddress = IPaddress; elem->socket = socket; elem->ready = NO; //inizialmente si crea l'elemento ma non è realmente connesso ! elem->impegnato = NO; elem->next = NULL; elem->enemy = NULL; //puntatore al socket dell'avversario elem->stato = 0; elem->last=0; memset(elem->username,0,sizeof(elem->username)); memset(elem->buffer,0,sizeof(elem->buffer)); return elem; //ritorno l'elemento creato } Codice:
for(i=0;i<=fdmax;i++) { if(FD_ISSET(i,&read_fds)){ //controlla se un descrittore è settato if (i==listener) // se è il listener vuol dire che c'è una nuova connessione in sospeso { //gestisco la nuova connessione addrlen = sizeof(clientaddr); newfd=accept(listener,(struct sockaddr*)&clientaddr,&addrlen); if(newfd==-1) { perror("errore nell'accept"); exit(1); } printf("connessione stabilita con il client\n"); FD_SET(newfd,&master); //setto il descrittore del socket appena connesso nel master if (newfd>fdmax) fdmax=newfd; //fdmax segnala quale è il più alto descrittore //creo un elemento del tipo Player socket newfd e ind IPaddress e lo inserisco nella lista ""inconnection" client=creatElem(newfd,clientaddr.sin_addr.s_addr); addToList(client); printf("Il nuovo elemento puntato è : %s \n",client->username); } else { // gestisco dei dati provenienti da uno dei client che sono o nella lista connessi client=elem_findbysock(i); if (client==NULL) { printf("il client non esiste, deve esserci stato un errore\n"); exit(1); } //è stato trovato un client, verifichiamo in che stato si trova tale client ...................... Come è possibile ? Dove ho sbagliato ?? Ultima modifica di aeroxr1 : 15-07-2014 alle 16:51. |
16-07-2014, 18:33 | #77 | ||
Senior Member
Iscritto dal: Mar 2006
Messaggi: 2049
|
Allora ho deciso passo alla codifica del numero in un char da 4byte con sprintf come mi ha consigliato @Daniels118
(con la shift non sono sicuro sia riuscito ad implementarla nel modo corretto) Quindi farò così : Quote:
Quote:
p.s : in effetti potrei anche evitare di ricevere \0 , però mi potrebbe tornare utile quando chiamerò la funzione di conversione da stringa ad intero Ultima modifica di aeroxr1 : 17-07-2014 alle 00:20. |
||
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 01:29.