Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
Tutto e di + - Pacchetti tcp Best Way?
Forum - Tutto e di + - Pacchetti tcp Best Way?

Avatar
Thejuster (Admin)
Guru^2


Messaggi: 2298
Iscritto: 04/05/2008

Segnala al moderatore
Postato alle 19:53
Sabato, 29/09/2018
Salve ragazzi.
Lasciando da parte il discorso della dll, risolvero' compilando il programma a linea di comando.

Per il mio progetto Mire Engine aka ex mmo rpgmaker.

Cercavo un modo per ottimizzare la velocità di elaborazione dei dati di un server.

Ho eseguito diversi test sia utilizzando cpp che c#. Praticamente cambia poco o nulla.
Il discorso è un'altro a questo punto.

Guardando sorgenti di altri server potenti noto che riescono a mantenere fino a 4000 utenti online in contemporanea e inviando informazioni in tempo reale.

Mi è sorto un dubbio quando provavo ad inviare dei pacchetti.

Noto con un certo dispiacere che per inviare anche una semplice stringa si supera e 100 byte.

Purtroppo devo pur dire al server:
Guarda che tizio ha fatto login.
Si sta muovendo in x / y,
Utilizza oggetto, sta attaccando.

Ma se il flusso di dati da inviare velocemente e troppo alto, il server non riuscirà nemmeno a tenerne 10 di utenti
Figuriamoci 4000.

Conoscete qualche trucco?
Io avevo pensato di inviare al max una sequenza di valori hex per specificare la funzione. Ad esempio
0xa4e6 = login
0x6e66 = login successo
0x65e66 = login fallito

Ma resta sempre il problema delle coordinate da inviare per ogni Player e per o ogni azione da eseguire. Tipo
Sapere se 1 utente e girato si spalle mentre l'altro è seduto.

Qualche idea o teoria?


https://mire.forumfree.it/ - Mire Engine
C# UI Designer
PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6230
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 23:09
Sabato, 29/09/2018
Per qualsiasi azione in "tempo reale" (come nei giochi multiplayer online) non devi usare TCP! Dovresti usare UDP.

https://gafferongames.com/post/udp_vs_tcp/

Un protocollo binario e' sicuramente piu' veloce di uno testuale, se ben progettato.


Il mio blog: https://piero.dev
PM Quote
Avatar
Thejuster (Admin)
Guru^2


Messaggi: 2298
Iscritto: 04/05/2008

Segnala al moderatore
Postato alle 10:02
Domenica, 30/09/2018
uhmm si questo indubbiamente.
l'upd è molto più veloce del tpc.


Mi domando una cosa, perché è il server a dover gestire anche tutti i movimenti?
questo non dovrebbe farlo il client come lavoro?

ad esempio questo è nel server

Codice sorgente - presumibilmente C#

  1. /*==========================================
  2.  * Move bl and do func* with va_list while moving.
  3.  * Movement is set by dx dy which are distance in x and y
  4.  *------------------------------------------*/
  5. int map_foreachinmovearea(int (*func)(struct block_list*,va_list), struct block_list* center, int16 range, int16 dx, int16 dy, int type, ...)
  6. {
  7.         int bx, by, m;
  8.         int returnCount = 0;  //total sum of returned values of func() [Skotlex]
  9.         struct block_list *bl;
  10.         int blockcount = bl_list_count, i;
  11.         int16 x0, x1, y0, y1;
  12.         va_list ap;
  13.  
  14.         if ( !range ) return 0;
  15.         if ( !dx && !dy ) return 0; //No movement.
  16.  
  17.         m = center->m;
  18.  
  19.         struct map_data *mapdata = map_getmapdata(m);
  20.  
  21.         x0 = center->x - range;
  22.         x1 = center->x + range;
  23.         y0 = center->y - range;
  24.         y1 = center->y + range;
  25.  
  26.         if ( x1 < x0 )
  27.                 SWAP(x0, x1);
  28.         if ( y1 < y0 )
  29.                 SWAP(y0, y1);
  30.  
  31.         if( dx == 0 || dy == 0 ) {
  32.                 //Movement along one axis only.
  33.                 if( dx == 0 ){
  34.                         if( dy < 0 ) //Moving south
  35.                                 y0 = y1 + dy + 1;
  36.                         else //North
  37.                                 y1 = y0 + dy - 1;
  38.                 } else { //dy == 0
  39.                         if( dx < 0 ) //West
  40.                                 x0 = x1 + dx + 1;
  41.                         else //East
  42.                                 x1 = x0 + dx - 1;
  43.                 }
  44.  
  45.                 x0 = i16max(x0, 0);
  46.                 y0 = i16max(y0, 0);
  47.                 x1 = i16min(x1, mapdata->xs - 1);
  48.                 y1 = i16min(y1, mapdata->ys - 1);
  49.  
  50.                 for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) {
  51.                         for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ) {
  52.                                 if ( type&~BL_MOB ) {
  53.                                         for( bl = mapdata->block[ bx + by * mapdata->bxs ]; bl != NULL; bl = bl->next ) {
  54.                                                 if( bl->type&type &&
  55.                                                         bl->x >= x0 && bl->x <= x1 &&
  56.                                                         bl->y >= y0 && bl->y <= y1 &&
  57.                                                         bl_list_count < BL_LIST_MAX )
  58.                                                         bl_list[ bl_list_count++ ] = bl;
  59.                                         }
  60.                                 }
  61.                                 if ( type&BL_MOB ) {
  62.                                         for( bl = mapdata->block_mob[ bx + by * mapdata->bxs ]; bl != NULL; bl = bl->next ) {
  63.                                                 if( bl->x >= x0 && bl->x <= x1 &&
  64.                                                         bl->y >= y0 && bl->y <= y1 &&
  65.                                                         bl_list_count < BL_LIST_MAX )
  66.                                                         bl_list[ bl_list_count++ ] = bl;
  67.                                         }
  68.                                 }
  69.                         }
  70.                 }
  71.         } else { // Diagonal movement
  72.                 x0 = i16max(x0, 0);
  73.                 y0 = i16max(y0, 0);
  74.                 x1 = i16min(x1, mapdata->xs - 1);
  75.                 y1 = i16min(y1, mapdata->ys - 1);
  76.  
  77.                 for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) {
  78.                         for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ) {
  79.                                 if ( type & ~BL_MOB ) {
  80.                                         for( bl = mapdata->block[ bx + by * mapdata->bxs ]; bl != NULL; bl = bl->next ) {
  81.                                                 if( bl->type&type &&
  82.                                                         bl->x >= x0 && bl->x <= x1 &&
  83.                                                         bl->y >= y0 && bl->y <= y1 &&
  84.                                                         bl_list_count < BL_LIST_MAX )
  85.                                                 if( ( dx > 0 && bl->x < x0 + dx) ||
  86.                                                         ( dx < 0 && bl->x > x1 + dx) ||
  87.                                                         ( dy > 0 && bl->y < y0 + dy) ||
  88.                                                         ( dy < 0 && bl->y > y1 + dy) )
  89.                                                         bl_list[ bl_list_count++ ] = bl;
  90.                                         }
  91.                                 }
  92.                                 if ( type&BL_MOB ) {
  93.                                         for( bl = mapdata->block_mob[ bx + by * mapdata->bxs ]; bl != NULL; bl = bl->next ) {
  94.                                                 if( bl->x >= x0 && bl->x <= x1 &&
  95.                                                         bl->y >= y0 && bl->y <= y1 &&
  96.                                                         bl_list_count < BL_LIST_MAX)
  97.                                                 if( ( dx > 0 && bl->x < x0 + dx) ||
  98.                                                         ( dx < 0 && bl->x > x1 + dx) ||
  99.                                                         ( dy > 0 && bl->y < y0 + dy) ||
  100.                                                         ( dy < 0 && bl->y > y1 + dy) )
  101.                                                         bl_list[ bl_list_count++ ] = bl;
  102.                                         }
  103.                                 }
  104.                         }
  105.                 }
  106.  
  107.         }
  108.  
  109.         if( bl_list_count >= BL_LIST_MAX )
  110.                 ShowWarning("map_foreachinmovearea: block count too many!\n");
  111.  
  112.         map_freeblock_lock();   // Prohibit the release from memory
  113.  
  114.         for( i = blockcount; i < bl_list_count; i++ )
  115.                 if( bl_list[ i ]->prev ) { //func() may delete this bl_list[] slot, checking for prev ensures it wasn't queued for deletion.
  116.                         va_start(ap, type);
  117.                         returnCount += func(bl_list[ i ], ap);
  118.                         va_end(ap);
  119.                 }
  120.  
  121.         map_freeblock_unlock(); // Allow Free
  122.  
  123.         bl_list_count = blockcount;
  124.         return returnCount;
  125. }



Di solito il server elabora solo informazioni e restituisce valori al client, o sbaglio?
In questo caso, il server fà un lavoro impressionante. Ma diversamente da come pensavo e forse un motivo ci sarà pure.

Può darsi che il client non elaborando tutti questi dati sia più veloce? facendo fare tutto il lavoro sporco al server?
Può darsi che il lag dipende non dal server scritto male, ma da client che deve effettuare troppe operazioni?

non anche che ci sono funzioni di trigonometria per calcolare celle di spostamento, se ci sono eventuali ostacoli etc.


per quanto riguardo i socket credo che usi il protocollo TPC.

Codice sorgente - presumibilmente C++

  1. #include "socket.hpp"
  2.  
  3. #include <stdlib.h>
  4.  
  5. #ifdef WIN32
  6.         #include "winapi.hpp"
  7. #else
  8.         #include <errno.h>
  9. #include <netinet/tcp.h>
  10.         #include <net/if.h>
  11.         #include <unistd.h>
  12. #include <sys/ioctl.h>
  13.         #include <netdb.h>
  14.         #include <arpa/inet.h>




per il discorso dei pacchetti ecco come fanno

Codice sorgente - presumibilmente C++

  1. 0x64
  2.  
  3. struct PACKET_CA_LOGIN {  /* this+0x0 */ short PacketType  /* this+0x2 */ unsigned long Version  /* this+0x6 */ unsigned char ID[24]  /* this+0x1e */ unsigned char Passwd[24]  /* this+0x36 */ unsigned char clienttype }
  4.  
  5.  
  6. 0x6a
  7. struct PACKET_AC_REFUSE_LOGIN {  /* this+0x0 */ short PacketType  /* this+0x2 */ unsigned char ErrorCode  /* this+0x3 */ char blockDate[20] }
  8.  
  9.  
  10. 0x8d
  11. struct PACKET_ZC_NOTIFY_CHAT {  /* this+0x0 */ short PacketType  /* this+0x2 */ short PacketLength  /* this+0x4 */ unsigned long GID  /* this+0x8 */ char msg[...] }



QUindi come funziona?

si invia al server un dato binario di appena qualche byte e successivamente valori?



https://mire.forumfree.it/ - Mire Engine
C# UI Designer
PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6230
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 4:29
Martedì, 02/10/2018
Testo quotato

Postato originariamente da Thejuster:
Di solito il server elabora solo informazioni e restituisce valori al client, o sbaglio?



Solitamente e' la maniera in cui funziona (ma non necessariamente, anche i client possono elaborare dati).


Testo quotato

Postato originariamente da Thejuster:
Può darsi che il client non elaborando tutti questi dati sia più veloce? facendo fare tutto il lavoro sporco al server?



Non e' tanto una questione di velocita', ma di assicurarsi che ci sia un'unica fonte "veritiera" dello stato del gioco... spostando il processing al server, il client invia il cambio di posizione (dx, dy), se il cambio di posizione viene ricevuto (che potrebbe non succedere, ad esempio a causa di un errore di rete o di un mancato pacchetto nel caso frequente di UDP), il server sposta il giocatore e aggiorna lo stato del gioco. Se il processing avviene sul client, penso sia piu' complicato sincronizzare il tutto..

Testo quotato

Postato originariamente da Thejuster:
Può darsi che il lag dipende non dal server scritto male, ma da client che deve effettuare troppe operazioni?



Forse.

Testo quotato

Postato originariamente da Thejuster:
si invia al server un dato binario di appena qualche byte e successivamente valori?



Si invia al server un unico pacchetto, il pacchetto comincia con un header (PacketType) che viene usato poi dal server per sapere cosa aspettarsi dai parametri successivi. Se PacketType == PACKET_CA_LOGIN allora ci sara' un campo Version, ID, Passwd, ecc., se PacketType == PACKET_AC_REFUSE_LOGIN allora ci sara' un campo errorCode e blockDate, ecc.


Il mio blog: https://piero.dev
PM Quote
Avatar
Thejuster (Admin)
Guru^2


Messaggi: 2298
Iscritto: 04/05/2008

Segnala al moderatore
Postato alle 19:55
Martedì, 02/10/2018
Grazie mille piero mi hai chiarito un bel pò di perplessità.

In pratica voglio seguire l'esempio di questo server.
Che è stato sviluppato da centinaia di utenti e non da uno solo.
programmatori da tutto il mondo come japponesi, americani etc.

Questo server ne sfrutta 3 in realtà.

ovvero 3 server che lavorano come fossero uno solo.
forse è questo il trucco per tenere tante persone online e non avere un minimo di lag.

pensa un pò che ho testato il gioco utilizzando la mia connessione dati del cellulare.
e nemmeno un minimo di lag.

c'è 1 server che gestisce tutto il comparto Login e Logout.
un'altro che gestisce tutte le operazioni che fanno i giocatori come esempio, utilizzo di oggetti,
le loro caratteristiche etc.

un'altro che invece tiene solo le posizioni (coordinate e skill varie )

forse la soluzione migliore e proprio seguire il loro esempio e provare a vedere cosa succede.


https://mire.forumfree.it/ - Mire Engine
C# UI Designer
PM Quote