logolinksrand Hamburg City Freelancer Server Foren-Übersicht
Players:0/64    *Mod here*
Server Load:0 msec 
Deaths per Minute:0
logorechts  
  SERVERIP : hc.flserver.de:2302
Discord Community: https://discord.gg/xh4ckhY


 
  Portal  •  Forum-FAQ  •   Suchen  •  Registrieren  •  Einloggen, um private Nachrichten zu lesen  •  Login  
  Donation/Spenden  •   Donation List  •   HC Forum Rangsystem Info  •   Player Rankings  •   Banned Players  
/

   
 Tutorial zum Fixen der Loss-Berechnung Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Neues Thema eröffnenNeue Antwort erstellen
Autor Nachricht
Kalvin_Dukes







Beiträge: 34

Beitrag Titel: Tutorial zum Fixen der Loss-Berechnung
Verfasst am: 04.10.06 12:59
Antworten mit ZitatNach oben

Hallo FLHook Community,

ich habe mich in den letzten Wochen etwas mit FLHook beschäftigt und kann mit der Struktur langsam umgehen.
Neben einigen Erweiterungen, habe ich mich auch mit der internen Berechnung für den Loss-Wert beschäftigt.

Bei Fragen und Anmerkungen kann ich noch ein paar Tipps geben. Wie MSVC bedient wird, solltet ihr jedoch wissen.

Ich habe herausgefunden, dass FLHook den Loss-Wert falsch berechnet.
FLHook berechnet den Loss-Wert anhand der verlorenen Bytes pro Messintervall.
Folgende Berechnung zeigt das Problem an dieser Herangehensweise auf:

Bei einem kleinen Kampf:
30 bytes sent+received
3 bytes lost
bei einem großen Kampf:
3000 bytes sent+received
300 bytes lost -> Kick
Obwohl in beiden Fällen gleiche Werte von 10% loss waren.

Für einen vernünftigen Losswert müsste die Berechnung aber anders vonstatten gehen:
Loss wird normalerweise in % der verlorenen Bytes oder Pakete gerechnet.
Dazu teilt man die verlorenen Bytes oder Pakete mit der Gesamtzahl der gesendeten/empfangenen Bytes oder Pakete.

Ich habe für unseren Server die Änderung in einem Mod für FLHook implementiert und möchte sie euch nicht vorenthalten.

Dazu sind Änderungen an einigen Stellen des Codes nötig.

Vorbereitung:
Wir brauchen drei neue Variablen, um den vorherigen Wert der Verbindungsstatistiken zu spiechern.
Diese Speicherung ist nötig, weil die Verbindungsstatistik immer nur die Gesamtanzahl der Daten bereithält.

Beispiel:
Intervall 1 -> Drops = 2
Intervall 2 -> Drops = 4
Intervall 3 -> Drops = 7

Was aber nicht heisst, dass zwischen dem zweiten und dem dritten check 7 Pakete verloren gegangen sind, sondern lediglich 3. Ich hoffe, das macht es etwas klarer.

Hier die drei Variablen, die in der Datei hook.h in der Struct CLIENT_INFO hinzugefügt werden müssen.

Code:
   uint      iLastPacketsSent;
   uint      iLastPacketsReceived;
   uint      iLastPacketsDropped;


Das ganze sieht bei mir so aus:

Code:
struct CLIENT_INFO
{
// kill msgs
   uint      iShip;
   uint      iShipOld;
   mstime      tmSpawnTime;

   DamageList   dmgLast;

// money cmd
   list<MONEY_FIX> lstMoneyFix;

// anticheat
   uint      iTradePartner;

// change cruise disruptor behaviour
   bool      bCruiseActivated;
   bool      bThrusterActivated;
   bool      bEngineKilled;
   bool      bTradelane;

// idle kicks
   uint      iBaseEnterTime;
   uint      iCharMenuEnterTime;

// connection data   
   list<uint>   lstLoss;
   uint      iLastLoss;
   uint      iAverageLoss;
   list<uint>   lstPing;
   uint      iAveragePing;
   uint      iLastPacketsSent; // <----
   uint      iLastPacketsReceived; // <----
   uint      iLastPacketsDropped; // <----

// msg, wait and kick
   mstime      tmKickTime;

// eventmode
   uint      iLastExitedBaseID;
   bool      bDisconnected;

// f1 laming
   bool      bCharSelected;
   mstime      tmF1Time;
   mstime      tmF1TimeDisconnect;

// ignore usercommand
   list<IGNORE_INFO> lstIgnore;

// user settings
   DIEMSGTYPE   dieMsg;
   CHATSIZE   dieMsgSize;
   CHATSTYLE   dieMsgStyle;
   CHATSIZE   chatSize;
   CHATSTYLE   chatStyle;

// autobuy
   bool      bAutoBuyMissiles;
   bool      bAutoBuyMines;
   bool      bAutoBuyTorps;
   bool      bAutoBuyCD;
   bool      bAutoBuyCM;
   bool      bAutoBuyReload;

// MultiKillMessages
   uint      iKillsInARow;

// bans
   uint      iConnects; // incremented when player connects

// other
   wstring      wscHostname;


};


Die neuen Variablen müssen auch noch initialisiert werden. Das geschieht in der Datei HkInit.cpp in der Funktion ClearClientInfo. Hier der neue Code:

Code:
void ClearClientInfo(uint iClientID)
{
   ClientInfo[iClientID].dieMsg = DIEMSG_ALL;
   ClientInfo[iClientID].iShip = 0;
   ClientInfo[iClientID].iShipOld = 0;
   ClientInfo[iClientID].tmSpawnTime = 0;
   ClientInfo[iClientID].lstMoneyFix.clear();
   ClientInfo[iClientID].iTradePartner = 0;
   ClientInfo[iClientID].iBaseEnterTime = 0;
   ClientInfo[iClientID].iCharMenuEnterTime = 0;
   ClientInfo[iClientID].bCruiseActivated = false;
   ClientInfo[iClientID].lstLoss.clear();
   ClientInfo[iClientID].iLastLoss = 0;
   ClientInfo[iClientID].iAverageLoss = 0;
   ClientInfo[iClientID].lstPing.clear();
   ClientInfo[iClientID].iAveragePing = 0;
   ClientInfo[iClientID].iLastPacketsSent = 0; // <----
   ClientInfo[iClientID].iLastPacketsReceived = 0; // <----
   ClientInfo[iClientID].iLastPacketsDropped = 0; // <----
   ClientInfo[iClientID].tmKickTime = 0;
   ClientInfo[iClientID].iLastExitedBaseID = 0;
   ClientInfo[iClientID].bDisconnected = false;
   ClientInfo[iClientID].bCharSelected = false;
   ClientInfo[iClientID].tmF1Time = 0;
   ClientInfo[iClientID].tmF1TimeDisconnect = 0;

   DamageList dmg;
   ClientInfo[iClientID].dmgLast = dmg;
   ClientInfo[iClientID].dieMsgSize = CS_DEFAULT;
   ClientInfo[iClientID].chatSize = CS_DEFAULT;
   ClientInfo[iClientID].chatStyle = CST_DEFAULT;

   ClientInfo[iClientID].bAutoBuyMissiles = false;
   ClientInfo[iClientID].bAutoBuyMines = false;
   ClientInfo[iClientID].bAutoBuyTorps = false;
   ClientInfo[iClientID].bAutoBuyCD = false;
   ClientInfo[iClientID].bAutoBuyCM = false;
   ClientInfo[iClientID].bAutoBuyReload = false;

   ClientInfo[iClientID].lstIgnore.clear();
   ClientInfo[iClientID].iKillsInARow = 0;
   ClientInfo[iClientID].wscHostname = L"";
   ClientInfo[iClientID].bEngineKilled = false;
   ClientInfo[iClientID].bThrusterActivated = false;
   ClientInfo[iClientID].bTradelane = false;


}


Schließlich können wir an die eigentliche Ursache herangehen, die Loss-Berechnung:

Hier der originale Code der Funktion HkTimerUpdateLossData() in der Datei HkTimers.cpp

Code:
/**************************************************************************************************************
Update average loss data
**************************************************************************************************************/

void HkTimerUpdateLossData()
{
   try {
      // for all players
      struct PlayerData *pPD = 0;
      while(pPD = Players.traverse_active(pPD))
      {
         uint iClientID = HkGetClientIdFromPD(pPD);
         if(ClientInfo[iClientID].tmF1TimeDisconnect)
            continue;

         DPN_CONNECTION_INFO ci;
         if(HkGetConnectionStats(iClientID, ci) != HKE_OK)
            continue;

         ///////////////////////////////////////////////////////////////
         // update loss data
         if(ClientInfo[iClientID].lstLoss.size() >= (set_iLossKickFrame / (LOSS_INTERVALL / 1000)))
         {
            // calculate average loss
            ClientInfo[iClientID].iAverageLoss = 0;
            foreach(ClientInfo[iClientID].lstLoss, uint, it)
               ClientInfo[iClientID].iAverageLoss += (*it);

            ClientInfo[iClientID].iAverageLoss /= (uint)ClientInfo[iClientID].lstLoss.size();
         }

         // remove old lossdata
         while(ClientInfo[iClientID].lstLoss.size() >= (set_iLossKickFrame / (LOSS_INTERVALL / 1000)))
            ClientInfo[iClientID].lstLoss.pop_back();

//         CDPClientProxy *cdpClient = g_cClientProxyArray[iClientID - 1];
//         double d = cdpClient->GetLinkSaturation();      
//         ClientInfo[iClientID].lstLoss.push_front((uint)(cdpClient->GetLinkSaturation() * 100)); // loss per sec
         ClientInfo[iClientID].lstLoss.push_front(ci.dwBytesRetried - ClientInfo[iClientID].iLastLoss); // loss per sec
         ClientInfo[iClientID].iLastLoss = ci.dwBytesRetried;
      }
   } catch(...) { AddLog("Exception in %s", __FUNCTION__); }
}



Und hier schließlich und endlich der Code, der den Loss richtig berechnet.

Code:
void HkTimerUpdateLossData()
{
   try {
      // for all players
      float fLossPercentage;
      uint iNewDrops;
      uint iNewSent;
      uint iNewReceived;
      struct PlayerData *pPD = 0;
      while(pPD = Players.traverse_active(pPD))
      {
         uint iClientID = HkGetClientIdFromPD(pPD);
         if(ClientInfo[iClientID].tmF1TimeDisconnect)
            continue;

         DPN_CONNECTION_INFO ci;
         if(HkGetConnectionStats(iClientID, ci) != HKE_OK)
            continue;

         ///////////////////////////////////////////////////////////////
         // update loss data
         if(ClientInfo[iClientID].lstLoss.size() >= (set_iLossKickFrame / (LOSS_INTERVALL / 1000)))
         {
            // calculate average loss
            ClientInfo[iClientID].iAverageLoss = 0;
            foreach(ClientInfo[iClientID].lstLoss, uint, it)
               ClientInfo[iClientID].iAverageLoss += (*it);

            ClientInfo[iClientID].iAverageLoss /= (uint)ClientInfo[iClientID].lstLoss.size();
         }

         // remove old lossdata
         while(ClientInfo[iClientID].lstLoss.size() >= (set_iLossKickFrame / (LOSS_INTERVALL / 1000)))
            ClientInfo[iClientID].lstLoss.pop_back();

         //sum of Drops = Drops guaranteed + drops non-guaranteed
         iNewDrops = (ci.dwPacketsRetried + ci.dwPacketsDropped) - ClientInfo[iClientID].iLastPacketsDropped;
         //Sent packets = sent guaranteed + sent non-guaranteed
         iNewSent = (ci.dwPacketsSentGuaranteed + ci.dwPacketsSentNonGuaranteed) - ClientInfo[iClientID].iLastPacketsSent;
         //Received packets = received guaranteed + received non-guaranteed
         iNewReceived = (ci.dwPacketsReceivedGuaranteed + ci.dwPacketsReceivedNonGuaranteed) - ClientInfo[iClientID].iLastPacketsReceived;
         
         // % of Packets Lost = Drops / (sent+received) * 100
         fLossPercentage = (float)((float)iNewDrops /((float)iNewSent + (float)iNewReceived)) *100;
         
         //add last loss to List lstLoss and put current value into iLastLoss
         ClientInfo[iClientID].lstLoss.push_front(ClientInfo[iClientID].iLastLoss);
         ClientInfo[iClientID].iLastLoss = (uint)fLossPercentage;

         //begin of debug-output of Loss (not nessecary)
         if ( set_iDebug >=2 && iNewDrops >0)
         {
         AddLog("LOSSDATA: %f AVG: %u ID=%s",fLossPercentage, ClientInfo[iClientID].iAverageLoss, wstos(Players.GetActiveCharacterName(iClientID)).c_str());
         AddLog("Packetsretried+dropped=%u", iNewDrops);
         AddLog("PacketsSent=%u", iNewSent);
         AddLog("PacketsRevcd=%u", iNewReceived);
         }
         //end of debug-output of Loss (not nessecary)
            
         //Fill new ClientInfo-variables with current values
         ClientInfo[iClientID].iLastPacketsSent = ci.dwPacketsSentGuaranteed + ci.dwPacketsSentNonGuaranteed;
         ClientInfo[iClientID].iLastPacketsReceived = ci.dwPacketsReceivedGuaranteed + ci.dwPacketsReceivedNonGuaranteed;
         ClientInfo[iClientID].iLastPacketsDropped = ci.dwPacketsRetried + ci.dwPacketsDropped;


         
      }
   } catch(...) { AddLog("Exception in %s", __FUNCTION__); }
}


Vielleicht kann ich demnächst noch ein paar Files hochladen, dann sollte das auch einfacher auszutauschen sein.

_________________
mfg
Kalvin_Dukes
Technical Co-Admin
24/7 - German - Freeworlds - RPG @ www.sw-server.net
Kalvin_Dukes is offline Benutzer-Profile anzeigenPrivate Nachricht senden
w0dk4
Lieutenant


financial_expert_bronze time_bandit_gold jumpholefinder_bronze rpgchar

urgestein_gold hcl04_silber developer kreuz_gold


Deppenadmin² und sich damit abgefunden !
Playtime: 1008h
Webmissions: 8


Beiträge: 9012
Wohnort: Heidelberg

Beitrag Titel:
Verfasst am: 04.10.06 13:33
Antworten mit ZitatNach oben

Dank dir für das Tutorial.

Weißt du zufällig was es mit den Guaranteed und NonGuaranteed Packeten auf sich hat?
Aber gute Idee, die ganzen Packetwerte zu addieren, bin ich mal gespannt wie aussagekräftig das ist

_________________
http://www.freeworldstidesofwar.com
http://the-starport.net
w0dk4 is offline Benutzer-Profile anzeigenPrivate Nachricht senden
Kalvin_Dukes







Beiträge: 34

Beitrag Titel:
Verfasst am: 04.10.06 13:53
Antworten mit ZitatNach oben

w0dk4 hat folgendes geschrieben:
Dank dir für das Tutorial.

Weißt du zufällig was es mit den Guaranteed und NonGuaranteed Packeten auf sich hat?


Ich habe selbst auch sehr lange nach einer Antwort auf diese Frage gesucht.
Habe aber weder bei Microsoft, noch bei DirectX/DirectPlay irgend ne Beschreibung gefunden.
Von den Werten PacktetsRetried und PacketsDropped habe ich dann darauf geschlossen, dass das eine wahrscheinlich TCP (guaranteed/retried) und das andere UDP(non-guaranteed/dropped) bedeutet.
Da Freelancer aber eigentlich nur UDP-Endpoints aufmacht und trotzdem ab und an was in <guaranteed> steht, hab ich die kurzerhand aufsummiert, um sicherzugehen.

w0dk4 hat folgendes geschrieben:
Aber gute Idee, die ganzen Packetwerte zu addieren, bin ich mal gespannt wie aussagekräftig das ist


Das läuft bei uns seit letzter Woche auch auf dem Live-Server mit. Bisher hats wirklich nur Leute mit Connection-Problemen (Versatel) und P2P-süchtige gekickt, die vergessen hatten, das auszumachen.

Achja, die Schwellwerte, die wir benutzen, um P2P-Leute zu erinnern, sind:
avg. Ping 300 über 60 Messungen
avg. Loss 10 über 60 Messungen

_________________
mfg
Kalvin_Dukes
Technical Co-Admin
24/7 - German - Freeworlds - RPG @ www.sw-server.net
Kalvin_Dukes is offline Benutzer-Profile anzeigenPrivate Nachricht senden
Sen







Beiträge: 4

Beitrag Titel: /loss anzeige
Verfasst am: 25.09.07 13:19
Antworten mit ZitatNach oben

hallo.

kann ich den loss auch über einen befehl aufrufen,wenn ich das jetzt auf nem eigenen server mach,also für user und co.
ich war auch schon in diesem coder-forum,aber da hab ich nix zu gefunden.
also ich meine,wenn ich das jetzt in den datein umsetze und per rebuild flhook im visual... mache.
da ich irgentwie keinen befehl gefunden habe,den ich dafür einbauen kann.
ich danke euch schonmal für eure aufmerksamkeit und die eventuelle hilfe.

Mfg Sen
Sen is offline Benutzer-Profile anzeigenPrivate Nachricht senden
w0dk4
Lieutenant


financial_expert_bronze time_bandit_gold jumpholefinder_bronze rpgchar

urgestein_gold hcl04_silber developer kreuz_gold


Deppenadmin² und sich damit abgefunden !
Playtime: 1008h
Webmissions: 8


Beiträge: 9012
Wohnort: Heidelberg

Beitrag Titel:
Verfasst am: 25.09.07 13:24
Antworten mit ZitatNach oben

Einfach bei void CCmds::PrintPlayerInfo(HKPLAYERINFO pi)
loss=%u und dann hinten ClientInfo[pi.iClientID].iAverageLoss
dazu schreiben.

Dann siehst du bei getplayers usw. auch den Loss.
Für ein user Command kannst du im Coder Forum schauen, ist wie bei dem Ping Command.

_________________
http://www.freeworldstidesofwar.com
http://the-starport.net
w0dk4 is offline Benutzer-Profile anzeigenPrivate Nachricht senden
Sen







Beiträge: 4

Beitrag Titel:
Verfasst am: 25.09.07 13:43
Antworten mit ZitatNach oben

ui das ging aber schnell.

ersteinmal ein riesen dank.
ja,also die sache mit dem void CCmds::PrintPlayerInfo(HKPLAYERINFO pi) hab ich ja,aber bei der sache mit dem loss befehl stehe ich bissel neben mir.
der loss muß doch ne andere berechnung als die des pings nutzen oder?
ich hatte zwar den code aus dem coder forum schonmal probiert für ping/loss aber dieser zeigte mir egal was ich tat immer nur meinen ping und 0 loss.
das selbe wahr auch bei testplayern der fall,die ich darum gebeten hatte ne schlechte verbindung durch diverse sachen vor zutäuschen.
loss blieb immer bei 0.
und wenn ich versuchte mir den ping von anderen an zu sehen,zeigte er mir auch immer nur meinen.
vileicht hab ich ja auch nur einfach was falsch gemacht?
falls du mir da vileicht noch nen paar tipps geben kannst wäre ich dir sehr dankbar dafür.
bis dahin,

Mfg Sen
Sen is offline Benutzer-Profile anzeigenPrivate Nachricht senden
Sen







Beiträge: 4

Beitrag Titel:
Verfasst am: 27.09.07 15:06
Antworten mit ZitatNach oben

hallo,der ich nochmal.

ich weiß ja nicht,aber in dem coderforum scheint wohl niemand mehr zu sein,zumindest gibts da keinen support,geschweigeden das ich da mal jemanden sehe.
kann mir nicht jemand von euch weiter helfen?
oder habt ihr noch ne idee,wo ich noch infos dazu sammeln kann.
wäre euch sehr dankbar.

Mfg Sen
Sen is offline Benutzer-Profile anzeigenPrivate Nachricht senden
Beiträge der letzten Zeit anzeigen:      
Neues Thema eröffnenNeue Antwort erstellen


 Gehe zu:   



Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.


 



Kurzmitteilungen
Last 10 Deaths


Google





   
  6 users on website
powered by 230 volt, phpBB with modifications by Niwo. Alle Zeiten sind GMT + 1 Stunde
This page has been viewed 230358284 times.
Servertime: 22:48:28 Current server uptime: 32 days, 0 users, load average: 0.03, 0.03, Server Disk Space free: 24865 MB


Spendenkontostand / donating account balance
Page generation time: 0.3677s (PHP: 49% - SQL: 51%) - SQL queries: 20 - GZIP disabled - Debug off