|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: Feb 2002
Messaggi: 906
|
c++ tempi in ms in ricezione pacchetti
voglio sapere il tempo di ricezione pacchetti, il tempo tra una ricezione e l'altra, inviato dal client al server quindi ho fatto questo:
Nella routine di recezione ovvero in pseudocode i pacchetti sono inviati in modo continuo: //globale float p=0.0f; float s=0.0f; int bytes=0; case FD_READ: bytes=recv();//ricezione pacchetto p=time; stampaListbox((p-s)*12024); s=p; che ne dite hp provato e mi stampa gli ms niente male... è giusto o è errato questo odo di procedere? |
![]() |
![]() |
![]() |
#2 | |
Senior Member
Iscritto dal: Jun 2006
Città: Inverno: Novgorod. Estate: Haifa
Messaggi: 879
|
Quote:
Hai visibilità degli interupt?
__________________
Hosti non solum dandam esse viam ad fugiendum, sed etiam muniendam / Ceterum censeo Carthaginem esse delendam / Et facere et pati fortia romanum est / Nemo Romanorum pacis mentionem habere dignatus est / Roma locuta, causa finita Milla |
|
![]() |
![]() |
![]() |
#3 | |
Senior Member
Iscritto dal: Feb 2002
Messaggi: 906
|
Quote:
stampaListbox((p-s)*12024); questo sopra l'ho scritto male stampaListbox((p-s)*1024); //giusto |
|
![]() |
![]() |
![]() |
#4 | |
Senior Member
Iscritto dal: Jun 2006
Città: Inverno: Novgorod. Estate: Haifa
Messaggi: 879
|
Quote:
__________________
Hosti non solum dandam esse viam ad fugiendum, sed etiam muniendam / Ceterum censeo Carthaginem esse delendam / Et facere et pati fortia romanum est / Nemo Romanorum pacis mentionem habere dignatus est / Roma locuta, causa finita Milla |
|
![]() |
![]() |
![]() |
#5 | |
Senior Member
Iscritto dal: Feb 2002
Messaggi: 906
|
Quote:
tra una ricezione e l'altra prendo il tempo del clock e lo sottraggo al vecchio tempo moltiplicando per 1024 ottenendo i ms. La mia è un'applicazione con winsock. cosa sono queste routine di interrupt che dici? |
|
![]() |
![]() |
![]() |
#6 |
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
1 secondo = 1024 millisecondi, questa mi è nuova
![]() ![]() ![]() |
![]() |
![]() |
![]() |
#7 | |
Senior Member
Iscritto dal: Jun 2006
Città: Inverno: Novgorod. Estate: Haifa
Messaggi: 879
|
Quote:
![]() ![]() ![]()
__________________
Hosti non solum dandam esse viam ad fugiendum, sed etiam muniendam / Ceterum censeo Carthaginem esse delendam / Et facere et pati fortia romanum est / Nemo Romanorum pacis mentionem habere dignatus est / Roma locuta, causa finita Milla |
|
![]() |
![]() |
![]() |
#8 | |
Senior Member
Iscritto dal: Jun 2006
Città: Inverno: Novgorod. Estate: Haifa
Messaggi: 879
|
Quote:
1ms = 1 sec / 1000 1us = 1 sec / 1000000 1ns = 1 sec / 1000000000 ti confondi con i moltiplicatori dei byte ![]()
__________________
Hosti non solum dandam esse viam ad fugiendum, sed etiam muniendam / Ceterum censeo Carthaginem esse delendam / Et facere et pati fortia romanum est / Nemo Romanorum pacis mentionem habere dignatus est / Roma locuta, causa finita Milla |
|
![]() |
![]() |
![]() |
#9 | |
Senior Member
Iscritto dal: Jun 2006
Città: Inverno: Novgorod. Estate: Haifa
Messaggi: 879
|
Quote:
![]() ![]()
__________________
Hosti non solum dandam esse viam ad fugiendum, sed etiam muniendam / Ceterum censeo Carthaginem esse delendam / Et facere et pati fortia romanum est / Nemo Romanorum pacis mentionem habere dignatus est / Roma locuta, causa finita Milla |
|
![]() |
![]() |
![]() |
#10 | |
Senior Member
Iscritto dal: Feb 2002
Messaggi: 906
|
Quote:
1 secondo = 1000 ma io calcolo su 1024 (byte) (un pacchetto da 58 bytes) ho scritto in pseudo code... un giorno te lo spiegherò ![]() |
|
![]() |
![]() |
![]() |
#11 | |
Senior Member
Iscritto dal: Jun 2006
Città: Inverno: Novgorod. Estate: Haifa
Messaggi: 879
|
Quote:
PS: so cos'è uno psdcode
__________________
Hosti non solum dandam esse viam ad fugiendum, sed etiam muniendam / Ceterum censeo Carthaginem esse delendam / Et facere et pati fortia romanum est / Nemo Romanorum pacis mentionem habere dignatus est / Roma locuta, causa finita Milla |
|
![]() |
![]() |
![]() |
#12 | |
Senior Member
Iscritto dal: Jun 2006
Città: Inverno: Novgorod. Estate: Haifa
Messaggi: 879
|
Quote:
__________________
Hosti non solum dandam esse viam ad fugiendum, sed etiam muniendam / Ceterum censeo Carthaginem esse delendam / Et facere et pati fortia romanum est / Nemo Romanorum pacis mentionem habere dignatus est / Roma locuta, causa finita Milla |
|
![]() |
![]() |
![]() |
#13 | |
Senior Member
Iscritto dal: Feb 2002
Messaggi: 906
|
Quote:
ma quello che mi interessa nel 3d che ho postato è sapere se qualcuno usava questo tipo di approccio oltre altri modi nel modo che ho scritto io (in pseudo code): i dati, in questo caso un pacchetto da 58 bytes vengono inviati di continuo dal client al server il server smista il pacchetto del client da 58 bytes a tutti i client ora nei clients nella notifica FD_READ: arriva il pacchetto che può essere un pacchetto perso oppure di 18 bytes oppure completo di 58 bytes. quando arriva completo di 58 bytes la tecnica che ho usato è appunto quella scritta sopra. ho un vecchio tempo sottraggo dal nuovo il vecchio (espresso in secondi) e calcolo il size rate del pacchetto ricevuto. Ripeto che quello che mi interessa sapere sono altri modi di calcolare gli ms oltre a questo che ho scritto io. Per quanto riguarda i bytes li tramuto in kb o viceversa calcolando o dividendo per 1024... ma questo esula da questo 3d. Le linee di codice postate è pseudo code!!! |
|
![]() |
![]() |
![]() |
#14 | |
Senior Member
Iscritto dal: Feb 2002
Messaggi: 906
|
Quote:
tempo = (s - p)*1000; Velocita = BytesRicevuti / tempo; questa invece è la velocità di trasferimento ma il modo di calcolare gli ms tramite FD_READ a te sembra strano o è una buona cosa? |
|
![]() |
![]() |
![]() |
#15 | |
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
Quote:
![]() |
|
![]() |
![]() |
![]() |
#16 | |
Senior Member
Iscritto dal: Jun 2006
Città: Inverno: Novgorod. Estate: Haifa
Messaggi: 879
|
Quote:
Avevo eseguito la misura scrivendo istruzioni nella routine di interrupt, ma avevo un hw costruito da noi (Motorola Coldfire + uCLinux) , quindi potevo fare ciò che volevo. Misurando i colpi di clk fra un in e il successivo ero preciso al us, misura verificata con oscilloscopio "piantato" sull'hw. Ma le nostre erano esigenze estreme. Se tu devi fare una misura di massima, credo che possa andare bene ciò che hai fatto.
__________________
Hosti non solum dandam esse viam ad fugiendum, sed etiam muniendam / Ceterum censeo Carthaginem esse delendam / Et facere et pati fortia romanum est / Nemo Romanorum pacis mentionem habere dignatus est / Roma locuta, causa finita Milla |
|
![]() |
![]() |
![]() |
#17 | |
Senior Member
Iscritto dal: Feb 2002
Messaggi: 906
|
Quote:
ti ringrazio... una cosa...(riformulo la domanda): Non so se sei pratico di winsock TCP ecc ecc. Ho sviluppato un netcode con winsock senza thread ne sui clients e ne sul server. I modi di operare sono svariati ovvero si può costruire o in modo bloccante o non-bloccante o asincrono. Ecco io ho scelto il modo asincrono lo puoi appunto vedere dall'evento di notifica FD_READ gli altri sono FD_WRITE FD_CLOSE ecc ecc. In questo modo che ho scelto si ha la possibilità, appunto asincrona di gestire + client in contemporanea (ecco perchè ho scelto questo metodo). Facendo i test in locale lancio il server e 3 client sul server uso una listbox dove stampo i valori dei tempi in ms del pacchetto inviato. nell'evento FD_READ del server arrivano i pacchetti di 58 bytes dove con recv() leggo il pacchetto del client 1 poi il 2 e il client 3, prendo il tempo (come esposto sopra) e stampo sulla listbox i valori in ms. I valori in ms sono buoni essi oscillano in un range di 16/60 ms. la mia domanda del thread era sapere se era giusto calcolare gli ms nella routine FD_READ ovvero tra un pacchetto ricevuto e un'altro. Ecco questo intendevo sapere oppure c'era un'altro modo? IL TEST valutato da me: Innanzitutto mi sembra lento, non capisco se è la stampa nella listbox che rallenta mi fà sembrare tutto rallentato in ricezione. In + nella listbox vedo i clients stampati in ordine all'inizio tipo: nome 0 16 ms nome 1 37 ms nome 2 24 ms ... e così via ... poi tutto ad un tratto stampa così: nome 0 38 ms nome 0 45 ms nome 0 33 ms nome 0 22 ms ... e così via per parecchio dove sembra che gli altri 2 client l'1 e il 2 non inviino dati. Poi inizia a stampare il client 2 poi di nuovo tutti e 3 e poi di nuovo un client qualsiasi. Spero che questo sotto sia uno spunto per una discussione: Questo è quanto ho letto su google a riguardo la tecnica dell'asincrono che è scritta in inglese e ci ho capito poco: Codice HTML:
The price you pay for using asynchronous sockets There is one disadvantage when using asynchronous sockets. Say you decide to send something to the computer you are connected with, and one command after, you try to perform another operation on the socket, chances are that the socket will return an error. The error is WSAEWOULDBLOCK (error number 10035). The good news is that this error is not a fatal error, but just means, "Try again later". The bad news is that in theory, you should be testing for this error specifically and trying to perform your action until it actually works and this error is no longer returned. Now this is annoying, since you can test for errors by just saying if (socketaction(s) ==SOCKET_ERROR) (here, socketaction() doesn’t mean anything. It is just an example). But WSAEWOULDBLOCK is an error also. That means you will have to specially test (call WSAGetLastError()) if WSAEWOULDBLOCK occurs and just repeatedly try again. I have found a cheap way around this which is not 100% guaranteed to work. When you perform your action and there was an error, test if WSAEWOULDBLOCK was returned. If it was returned then just Sleep (750) and try again. What’s so great about this? Well, you don’t have to loop, instead you just delay and try once again. Chances are, that after 750 milliseconds, the socket will be ready to perform your action. Questa in italiano e da quello che leggo mi sembra di capire che il modo non-bloccante asincrono sia il migliore ma se c'è una PENDENZA DI DATI che per un dato motivo deve essere ripetuta, per via dell'evento WSAEWOULDBLOCK che pare che non sia un errore, ma se si verifica questo evento c'è da aspettare un tot per il nuovo invio del pacchetto: Codice HTML:
3.4.2 Modo Operativo Non-Bloccante In riferimento all'esempio precedentemente introdotto, con il modo operativo non-bloccante, ci troviamo nella situazione in cui, verificata l'indisponibilità dell'utente cercato, si decida di interrompere la comunicazione e richiamare successivamente. Chiaramente, tale operazione, se effettuata in maniera continuativa, porta ad uno spreco di tempo e di risorse. Sarebbe, quindi, meglio spaziare equamente le nuove chiamate, in maniera tale da poter, nel frattempo, compiere altre azioni. In tal modo, inoltre. non si è vincolati al telefono, potendolo quindi adoperare per altre chiamate. Tutto ciò, è simile ad un'operazione socket non-bloccante : è necessario verificare a turno (poll), il completamento delle operazioni, ma, tale verifica, non deve essere effettuata troppo spesso per non sprecare le risorse di sistema. Nel nonblocking operation mode, una funzione Windows Sockets, appena chiamata, restituisce immediatamente il suo valore di ritorno. In alcuni casi, tale valore, indicherà un successo nell'esecuzione dell'operazione richiesta, in altri casi, esso indicherà un fallimento. Però, nel modo operativo non- bloccante, un fallimento non è necessariamente indice di un fatto negativo. Infatti il valore di ritorno della funzione che ha fallito, che sarà un valore di errore (ottenuto tramite una chiamata alla funzione WSAGetLastError()), può essere pari alla costante WSAEWOULDBLOCK, che letteralmente significa : "la funzione potrebbe essere bloccata, se ha da attendere fino al completamento di un'operazione, prima di ritornare". In tal caso, possono verificarsi due situazioni, in dipendenza della funzione chiamata. Nel primo caso, il valore di ritorno WSAEWOULDBLOCK indica che la DLL WinSock ha cominciato l'operazione, ma che, in questo momento, non è ancora stata completata (cioè, l'operazione è, come si dice, pendente). In tal caso, l'operazione verrà, eventualmente, completata successivamente, avendo modo (vedi successivo par. 3.5) di rilevare il completamento della stessa. Nella seconda situazione, invece, Il valore di ritorno già visto, indicherà che la DLL WinSock ha tentato di eseguire la richiesta fatta, ma ciò non è risultato attualmente possibile. In tale situazione, l'errore suddetto, indicherà il fatto che sarà necessario effettuare, successivamente, una nuova chiamata alla funzione di interesse. Il problema, con il modo non-bloccante, è che un'applicazione, per portare a termine un'operazione, o per rilevare il suo completamento, ha bisogno di richiamare una funzione più e più volte. Tutto ciò, implica un notevole sovraccarico del sistema, se il polling viene effettuata troppo spesso, oppure influenza in maniera avversa le prestazioni dell'applicazione, se tale verifica non viene effettuata sufficientemente spesso. Oltre a ciò, tale modalità operativa, complica anche l'implementazione del codice necessario. Il vantaggio, invece, con tale modo operativo, è quello di poter adoperare più socket, che hanno simultaneamente delle operazioni pendenti. Molte applicazioni, non-bloccanti, sono ibride, in quanto combinano l'uso delle socket non-bloccanti con la funzione bloccante select(), per multiplexare, le prime, in maniera efficiente. 3.4.3 Modo Operativo Asincrono Considerando, ancora, l'esempio di partenza, con la modalità operativa asincrona, ci ritroviamo nel terzo caso, in cui si è lasciato un messaggio alla persona cercata, per essere richiamati. In un tale caso, si delega, quindi, ad un altro, il compito di stabilire la comunicazione richiesta, avendo, nel frattempo, la libertà di poter eseguire qualsiasi altra azione, incluso l'uso del mezzo comunicativo per effettuare altre chiamate diverse. In quanto, se accadesse che la persona incaricata, trovasse la nostra linea occupata, sarà, ancora, suo compito quello di richiamare successivamente. L'asynchronous operation mode, è non-bloccante, in quanto, la funzione chiamata ritorna immediatamente, prima che l'azione richiesta sia stata completata. Ma, a differenza del modo operativo non-bloccante regolare, il valore di ritorno WSAEWOULDBLOCK indica che la DLL WinSock invierà un messaggio per notificare il caso in cui un'operazione pendente è stata completata, o quando un'operazione deve essere ritentata. Tutto ciò rende le operazioni molto più efficienti, consentendo anche delle prestazioni molto elevate. Risulta chiaro che, un tale modo operativo, è basato proprio sulle caratteristiche dell'ambiente operativo Windows, di conseguenza il suo codice sorgente non è compatibile con le Berkeley Sockets (che per tale modalità operativa adoperano la funzione signal()). Tuttavia, la sua semplicità ed efficienza, sono tali da rendere trascurabile tale mancanza di portabilità. Come dicevamo, la modalità operativa asincrona si avvantaggia della natura, basata sul sistema dei messaggi, dell'architettura Windows. Tale sistema è basato sugli oggetti (vedi par. 4.-.-); gli oggetti comunicano tra di loro passandosi dei messaggi. Tali messaggi, giungono agli oggetti in maniera asincrona, e, per ogni messaggio ricevuto, l'oggetto reagirà o compiendo un'azione specifica o inviando, sempre in maniera asincrona, dei messaggi di risposta. La modalità asincrona, delle Windows Sockets, adopera proprio tale sistema di messaggi, piuttosto che una continua ripetizione di chiamate di funzioni, superando, quindi, gli svantaggi, in termini di sfruttamento delle risorse di sistema, del precedente modo operativo. Per contro, c'è da dire che tale sistema risulta leggermente inferiore, rispetto a quello non-bloccante, in termini di prestazioni, in quanto, proprio il sistema dei messaggi richiede, di per sè, un certo ammontare di tempo nell'esecuzione delle notifiche e della loro successiva elaborazione, riducendo quindi la capacità complessiva di scambio dei dati (data throughput). Vedremo, nel paragrafo successivo, trattando gli stati delle socket, in che maniera vengano adoperate le funzioni asincrone, ed i tipi di messaggi elaborati, ed appositamente implementati per le Windows Sockets. Anche perchè nella ricezione dei pacchetti non ho bisogno di reinviarli se sono persi o il send non è andato a buon fine non uso UDP ma TCP molto + affidabile infatti uso nella ricezione questa tecnica: Codice HTML:
case FD_READ: if( (bytes) < sizeof(GAMEMSG_GENERIC) ) return TRUE; In questo modo evito, oltretutto, di processare pacchetti fasulli se qualche malintezionato vuole sendare dei byte arbitrari sul server Ultima modifica di okay : 29-08-2006 alle 09:02. |
|
![]() |
![]() |
![]() |
#18 |
Senior Member
Iscritto dal: Jun 2006
Città: Inverno: Novgorod. Estate: Haifa
Messaggi: 879
|
![]()
__________________
Hosti non solum dandam esse viam ad fugiendum, sed etiam muniendam / Ceterum censeo Carthaginem esse delendam / Et facere et pati fortia romanum est / Nemo Romanorum pacis mentionem habere dignatus est / Roma locuta, causa finita Milla |
![]() |
![]() |
![]() |
#19 |
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
la soluzione proposta (attendere 750 ms) fa schifo: quello che devi attendere per andare a colpo sicuro non sono i 750 ms, è il messaggio FD_WRITE; sennò a che serve?
se non ti va di attendere allora apri un altro thread e invia da là, magari usando socket bloccanti. |
![]() |
![]() |
![]() |
#20 | |
Senior Member
Iscritto dal: Feb 2002
Messaggi: 906
|
Quote:
Mentre FD_WRITE io per esempio non lo uso proprio, fosse questo il fatto? Voglio dire: sul server io uso FD_READ per ricevere il pacchetto e subito tramite ciclo (for i) li reinvio a tutti i client il tutto sempre dall'evento FD_READ e come finisco il ciclo (for i) di invio esco con return TRUE; dai messaggi. Il server dopo tutto deve smistare il pacchetto ai clients. In FD_WRITE, così come sul client, non ci passo mai. Ci passo uno sola volta nel server quando si collega un nuovo client. In pratica funziona così: Il client si collega e nel server entro nell'evento FD_ACCEPT: faccio che il client è true poi il server invia con send l'id al client ora come esco dal ciclo dei messaggi mi entra in FD_WRITE una sola volta. Forse da FD_READ, che serve per ricevere, non devo inviare con il (for i) da FD_READ in quanto il send si deve fare da FD_WRITE quando è pronto a scrivere. mi servirebbe qualcuno che mi spiegasse meglio. Il problema è che come ho fatto a me funziona tutto. Per esempio inviando come per una chat è perfetto. Ma se mando i dati in modo continuo vedo che gli exe (il server e 3 client aperti in locale) sembrano rallentare. Il server ad un certo punto sembra fermarsi e mettendo il focus sul form di un client il server ricomincia a stampare dati... non lo sò. Se passo il focus su un'altro client (cliccando con il mouse sul form) la finestra si ridisegna piano piano (intendo i bottoni la listbox ecc ecc) questo vale per tutti e 4 gli exe anzi il server.exe è ancora + lento a ridisegnarsi ed è anche naturale. Non ci sono errori di nessun tipo. Fosse che il send deve essere attuato da FD_WRITE:...?? mha... guarda non sò proprio. peròho questo link in inglese che mi intriga: http://www.gamedev.net/reference/art...rticle1297.asp in cui questa è la parte interessante: Codice HTML:
//Sending and Receiving Data The general idea is to create an infinite while loop in which you will continuously send data until you max out the buffer. When is happens, send () will return the error WSAWOULDBLOCK. This means that if it were a blocking socket, it would wait (stop execution) for more room in the buffer and then send. But since it isn’t, you get the error. So now that you’ve filled up the buffer, you just have to wait until more room becomes available so you can write again. And bingo! Up pops another FD_WRITE event. Do you have any idea how much trouble I had to go through to figure this out? You people are so darned lucky! Here’s an example of an FD_WRITE event handler: case FD_WRITE: // we can send data { // enter an infinite loop while(TRUE) { // read in more data from the file and store it in packet.data. in.read((char*)&packet.data, MAX_PACKET_SIZE); // increment the amount of data sent data_sent += strlen(packet.data); // send the packet off to the Server if it is filled if (send(wparam, (char*)(&packet), sizeof(PACKET), 0) == SOCKET_ERROR) { // check if the network buffer is full and can send no more // data. If so then break from the loop if (WSAGetLastError() == WSAEWOULDBLOCK) { // break from the loop – buffer is full break; } else // another error { // display an error message and clean up CleanUp(); return(0); } } } } break; |
|
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 09:02.