- attempt to add a client LAG checker to notify and disconnect clients that fall too far behind.

This commit is contained in:
Mark Vejvoda
2010-06-15 05:36:07 +00:00
parent b3b2d098b7
commit e091460f40
10 changed files with 157 additions and 80 deletions

View File

@@ -26,7 +26,7 @@ using namespace Shared::Platform;
namespace Glest{ namespace Game{ namespace Glest{ namespace Game{
const string mailString= "contact_game@glest.org"; const string mailString= "contact_game@glest.org";
const string glestVersionString= "v3.3.5-beta5"; const string glestVersionString= "v3.3.5-beta7";
string getCrashDumpFileName(){ string getCrashDumpFileName(){
return "glest" + glestVersionString + ".dmp"; return "glest" + glestVersionString + ".dmp";

View File

@@ -32,6 +32,9 @@ using namespace Shared::Platform;
namespace Glest{ namespace Game{ namespace Glest{ namespace Game{
// if FPS is less than this we start to skip 3D renders
int MIN_RENDER_FPS_ALLOWED = 15;
Game *thisGamePtr = NULL; Game *thisGamePtr = NULL;
// ===================================================== // =====================================================
@@ -51,7 +54,9 @@ Game::Game(Program *program, const GameSettings *gameSettings):
this->gameSettings= *gameSettings; this->gameSettings= *gameSettings;
scrollSpeed = Config::getInstance().getFloat("UiScrollSpeed","1.5"); scrollSpeed = Config::getInstance().getFloat("UiScrollSpeed","1.5");
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); MIN_RENDER_FPS_ALLOWED = Config::getInstance().getInt("MIN_RENDER_FPS_ALLOWED",intToStr(MIN_RENDER_FPS_ALLOWED).c_str());
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] MIN_RENDER_FPS_ALLOWED = %d\n",__FILE__,__FUNCTION__,__LINE__,MIN_RENDER_FPS_ALLOWED);
mouseX=0; mouseX=0;
mouseY=0; mouseY=0;
@@ -539,26 +544,28 @@ void Game::render() {
} }
void Game::renderWorker() { void Game::renderWorker() {
Chrono chrono; //Chrono chrono;
chrono.start(); //chrono.start();
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
//program->getWindow()->makeCurrentGl(); //program->getWindow()->makeCurrentGl();
//renderFps++; //renderFps++;
render3d(); if(renderFps >= MIN_RENDER_FPS_ALLOWED) {
render3d();
}
//if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d renderFps = %d took msecs: %d\n",__FILE__,__FUNCTION__,__LINE__,renderFps,chrono.getMillis()); //if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d renderFps = %d took msecs: %d\n",__FILE__,__FUNCTION__,__LINE__,renderFps,chrono.getMillis());
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
chrono.start(); //chrono.start();
render2d(); render2d();
//if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d renderFps = %d took msecs: %d\n",__FILE__,__FUNCTION__,__LINE__,renderFps,chrono.getMillis()); //if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d renderFps = %d took msecs: %d\n",__FILE__,__FUNCTION__,__LINE__,renderFps,chrono.getMillis());
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
chrono.start(); //chrono.start();
Renderer::getInstance().swapBuffers(); Renderer::getInstance().swapBuffers();
//if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d renderFps = %d took msecs: %d\n",__FILE__,__FUNCTION__,__LINE__,renderFps,chrono.getMillis()); //if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d renderFps = %d took msecs: %d\n",__FILE__,__FUNCTION__,__LINE__,renderFps,chrono.getMillis());
@@ -824,7 +831,7 @@ void Game::keyDown(char key){
Config &configKeys = Config::getInstance(std::pair<ConfigType,ConfigType>(cfgMainKeys,cfgUserKeys)); Config &configKeys = Config::getInstance(std::pair<ConfigType,ConfigType>(cfgMainKeys,cfgUserKeys));
if(key == configKeys.getCharKey("RenderNetworkStatus")) { if(key == configKeys.getCharKey("RenderNetworkStatus")) {
renderNetworkStatus= true; renderNetworkStatus= !renderNetworkStatus;
} }
else if(key == configKeys.getCharKey("ShowFullConsole")) { else if(key == configKeys.getCharKey("ShowFullConsole")) {
showFullConsole= true; showFullConsole= true;
@@ -963,33 +970,30 @@ void Game::keyUp(char key){
//send key to the chat manager //send key to the chat manager
chatManager.keyUp(key); chatManager.keyUp(key);
} }
else{ else {
switch(key){ Config &configKeys = Config::getInstance(std::pair<ConfigType,ConfigType>(cfgMainKeys,cfgUserKeys));
case 'N':
renderNetworkStatus= false; if(key == configKeys.getCharKey("RenderNetworkStatus")) {
break; //renderNetworkStatus= false;
case 'M': }
else if(key == configKeys.getCharKey("ShowFullConsole")) {
showFullConsole= false; showFullConsole= false;
break; }
case 'A': else if(key == configKeys.getCharKey("CameraRotateLeft") ||
case 'D': key == configKeys.getCharKey("CameraRotateRight")) {
gameCamera.setRotate(0); gameCamera.setRotate(0);
break; }
else if(key == configKeys.getCharKey("CameraRotateDown") ||
case 'W': key == configKeys.getCharKey("CameraRotateUp")) {
case 'S':
gameCamera.setMoveY(0); gameCamera.setMoveY(0);
break; }
else if(key == configKeys.getCharKey("CameraModeUp") ||
case vkUp: key == configKeys.getCharKey("CameraModeDown")) {
case vkDown:
gameCamera.setMoveZ(0); gameCamera.setMoveZ(0);
break; }
else if(key == configKeys.getCharKey("CameraModeLeft") ||
case vkLeft: key == configKeys.getCharKey("CameraModeRight")) {
case vkRight:
gameCamera.setMoveX(0); gameCamera.setMoveX(0);
break;
} }
} }
} }
@@ -1146,7 +1150,7 @@ void Game::render2d(){
str+= "Update FPS: "+intToStr(lastUpdateFps)+"\n"; str+= "Update FPS: "+intToStr(lastUpdateFps)+"\n";
str+= "GameCamera pos: "+floatToStr(gameCamera.getPos().x)+","+floatToStr(gameCamera.getPos().y)+","+floatToStr(gameCamera.getPos().z)+"\n"; str+= "GameCamera pos: "+floatToStr(gameCamera.getPos().x)+","+floatToStr(gameCamera.getPos().y)+","+floatToStr(gameCamera.getPos().z)+"\n";
str+= "Time: "+floatToStr(world.getTimeFlow()->getTime(),8)+"\n"; str+= "Time: "+floatToStr(world.getTimeFlow()->getTime(),8)+"\n";
str+= "Time Increment: "+floatToStr(world.getTimeFlow()->getTimeInc(),8)+"\n"; //str+= "Time Increment: "+floatToStr(world.getTimeFlow()->getTimeInc(),8)+"\n";
str+= "Triangle count: "+intToStr(renderer.getTriangleCount())+"\n"; str+= "Triangle count: "+intToStr(renderer.getTriangleCount())+"\n";
str+= "Vertex count: "+intToStr(renderer.getPointCount())+"\n"; str+= "Vertex count: "+intToStr(renderer.getPointCount())+"\n";
str+= "Frame count:"+intToStr(world.getFrameCount())+"\n"; str+= "Frame count:"+intToStr(world.getFrameCount())+"\n";

View File

@@ -1099,21 +1099,15 @@ void MenuStateCustomGame::simpleTask() {
if(publishToMasterserverThread == NULL || publishToMasterserverThread->getQuitStatus() == true || publishToMasterserverThread->getRunningStatus() == false) { if(publishToMasterserverThread == NULL || publishToMasterserverThread->getQuitStatus() == true || publishToMasterserverThread->getRunningStatus() == false) {
return; return;
} }
needToRepublishToMasterserver = false;
string newPublishToServerInfo = publishToServerInfo;
publishToServerInfo = "";
safeMutex.ReleaseLock(true); safeMutex.ReleaseLock(true);
if(republish == true) { if(republish == true) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
safeMutex.Lock(); string request = Config::getInstance().getString("Masterserver") + "addServerInfo.php?" + newPublishToServerInfo;
needToRepublishToMasterserver = false;
safeMutex.ReleaseLock(true);
string request = Config::getInstance().getString("Masterserver") + "addServerInfo.php?" + publishToServerInfo;
safeMutex.Lock();
publishToServerInfo = "";
safeMutex.ReleaseLock(true);
//printf("the request is:\n%s\n",request.c_str()); //printf("the request is:\n%s\n",request.c_str());
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d] the request is:\n%s\n",__FILE__,__FUNCTION__,__LINE__,request.c_str()); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d] the request is:\n%s\n",__FILE__,__FUNCTION__,__LINE__,request.c_str());
@@ -1125,10 +1119,10 @@ void MenuStateCustomGame::simpleTask() {
std::string serverInfo = SystemFlags::getHTTP(request); std::string serverInfo = SystemFlags::getHTTP(request);
//printf("the result is:\n'%s'\n",serverInfo.c_str()); //printf("the result is:\n'%s'\n",serverInfo.c_str());
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d] the result is:\n'%s'\n",__FILE__,__FUNCTION__,__LINE__,serverInfo.c_str()); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d] the result is:\n'%s'\n",__FILE__,__FUNCTION__,__LINE__,serverInfo.c_str());
// uncomment to enable router setup check of this server // uncomment to enable router setup check of this server
//if(serverInfo!="OK") //if(serverInfo!="OK")
if(EndsWith(serverInfo, "OK") == false) if(EndsWith(serverInfo, "OK") == false) {
{
safeMutex.Lock(); safeMutex.Lock();
showMasterserverError=true; showMasterserverError=true;
masterServererErrorToShow=serverInfo; masterServererErrorToShow=serverInfo;
@@ -1140,24 +1134,21 @@ void MenuStateCustomGame::simpleTask() {
safeMutex.Lock(); safeMutex.Lock();
bool broadCastSettings = needToBroadcastServerSettings; bool broadCastSettings = needToBroadcastServerSettings;
if(publishToMasterserverThread == NULL || publishToMasterserverThread->getQuitStatus() == true || publishToMasterserverThread->getRunningStatus() == false) { if(publishToMasterserverThread == NULL || publishToMasterserverThread->getQuitStatus() == true || publishToMasterserverThread->getRunningStatus() == false) {
return; return;
} }
needToBroadcastServerSettings=false;
safeMutex.ReleaseLock(true); safeMutex.ReleaseLock(true);
if(broadCastSettings) if(broadCastSettings) {
{
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
safeMutex.Lock();
needToBroadcastServerSettings=false;
safeMutex.ReleaseLock(true);
ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface(); ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface();
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(serverInterface->hasClientConnection() == true) { if(serverInterface->hasClientConnection() == true) {
//printf("Sending game settings broadcast since we have at least 1 client connected'\n"); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(publishToMasterserverThread == NULL || publishToMasterserverThread->getQuitStatus() == true || publishToMasterserverThread->getRunningStatus() == false) { if(publishToMasterserverThread == NULL || publishToMasterserverThread->getQuitStatus() == true || publishToMasterserverThread->getRunningStatus() == false) {
return; return;
@@ -1170,6 +1161,8 @@ void MenuStateCustomGame::simpleTask() {
return; return;
} }
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
serverInterface->setGameSettings(&gameSettings); serverInterface->setGameSettings(&gameSettings);
serverInterface->broadcastGameSetup(&gameSettings); serverInterface->broadcastGameSetup(&gameSettings);
} }

View File

@@ -37,6 +37,7 @@ namespace Glest{ namespace Game{
const int ClientInterface::messageWaitTimeout= 10000; //10 seconds const int ClientInterface::messageWaitTimeout= 10000; //10 seconds
const int ClientInterface::waitSleepTime= 10; const int ClientInterface::waitSleepTime= 10;
const int ClientInterface::maxNetworkCommandListSendTimeWait = 5;
ClientInterface::ClientInterface(){ ClientInterface::ClientInterface(){
clientSocket= NULL; clientSocket= NULL;
@@ -45,6 +46,8 @@ ClientInterface::ClientInterface(){
playerIndex= -1; playerIndex= -1;
gameSettingsReceived=false; gameSettingsReceived=false;
gotIntro = false; gotIntro = false;
lastNetworkCommandListSendTime = 0;
currentFrameCount = 0;
networkGameDataSynchCheckOkMap = false; networkGameDataSynchCheckOkMap = false;
networkGameDataSynchCheckOkTile = false; networkGameDataSynchCheckOkTile = false;
@@ -96,7 +99,7 @@ void ClientInterface::reset()
void ClientInterface::update() void ClientInterface::update()
{ {
NetworkMessageCommandList networkMessageCommandList; NetworkMessageCommandList networkMessageCommandList(currentFrameCount);
//send as many commands as we can //send as many commands as we can
while(!requestedCommands.empty()){ while(!requestedCommands.empty()){
@@ -107,15 +110,20 @@ void ClientInterface::update()
break; break;
} }
} }
if(networkMessageCommandList.getCommandCount()>0){
int lastSendElapsed = difftime(time(NULL),lastNetworkCommandListSendTime);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] lastSendElapsed = %d\n",__FILE__,__FUNCTION__,__LINE__,lastSendElapsed);
if(networkMessageCommandList.getCommandCount() > 0 || lastSendElapsed >= ClientInterface::maxNetworkCommandListSendTimeWait) {
sendMessage(&networkMessageCommandList); sendMessage(&networkMessageCommandList);
lastNetworkCommandListSendTime = time(NULL);
} }
// Possible cause of out of synch since we have more commands that need // Possible cause of out of synch since we have more commands that need
// to be sent in this frame // to be sent in this frame
if(!requestedCommands.empty()) { if(!requestedCommands.empty()) {
char szBuf[1024]=""; char szBuf[1024]="";
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] WARNING / ERROR, requestedCommands.size() = %d\n",__FILE__,__FUNCTION__,requestedCommands.size()); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] WARNING / ERROR, requestedCommands.size() = %d\n",__FILE__,__FUNCTION__,__LINE__,requestedCommands.size());
string sMsg = Config::getInstance().getString("NetPlayerName",Socket::getHostName().c_str()) + " may go out of synch: client requestedCommands.size() = " + intToStr(requestedCommands.size()); string sMsg = Config::getInstance().getString("NetPlayerName",Socket::getHostName().c_str()) + " may go out of synch: client requestedCommands.size() = " + intToStr(requestedCommands.size());
sendTextMessage(sMsg,-1); sendTextMessage(sMsg,-1);
@@ -440,6 +448,8 @@ void ClientInterface::updateLobby()
void ClientInterface::updateKeyframe(int frameCount) void ClientInterface::updateKeyframe(int frameCount)
{ {
currentFrameCount = frameCount;
bool done= false; bool done= false;
while(done == false) { while(done == false) {

View File

@@ -33,6 +33,7 @@ class ClientInterface: public GameNetworkInterface{
private: private:
static const int messageWaitTimeout; static const int messageWaitTimeout;
static const int waitSleepTime; static const int waitSleepTime;
static const int maxNetworkCommandListSendTimeWait;
private: private:
ClientSocket *clientSocket; ClientSocket *clientSocket;
@@ -48,6 +49,9 @@ private:
Ip ip; Ip ip;
int port; int port;
int currentFrameCount;
time_t lastNetworkCommandListSendTime;
public: public:
ClientInterface(); ClientInterface();
virtual ~ClientInterface(); virtual ~ClientInterface();
@@ -88,6 +92,8 @@ public:
virtual bool getConnectHasHandshaked() const { return gotIntro; } virtual bool getConnectHasHandshaked() const { return gotIntro; }
std::string getServerIpAddress(); std::string getServerIpAddress();
int getCurrentFrameCount() const { return currentFrameCount; }
protected: protected:
Mutex * getServerSynchAccessor() { return NULL; } Mutex * getServerSynchAccessor() { return NULL; }

View File

@@ -152,6 +152,9 @@ ConnectionSlot::ConnectionSlot(ServerInterface* serverInterface, int playerIndex
this->serverInterface = serverInterface; this->serverInterface = serverInterface;
this->playerIndex = playerIndex; this->playerIndex = playerIndex;
this->currentFrameCount = 0;
this->currentLagCount = 0;
this->lastReceiveCommandListTime = 0;
this->socket = NULL; this->socket = NULL;
this->slotThreadWorker = NULL; this->slotThreadWorker = NULL;
this->slotThreadWorker = new ConnectionSlotThread(this->serverInterface); this->slotThreadWorker = new ConnectionSlotThread(this->serverInterface);
@@ -274,6 +277,10 @@ void ConnectionSlot::update(bool checkForNewClients) {
NetworkMessageCommandList networkMessageCommandList; NetworkMessageCommandList networkMessageCommandList;
if(receiveMessage(&networkMessageCommandList)) { if(receiveMessage(&networkMessageCommandList)) {
currentFrameCount = networkMessageCommandList.getFrameCount();
lastReceiveCommandListTime = time(NULL);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] currentFrameCount = %d\n",__FILE__,__FUNCTION__,__LINE__,currentFrameCount);
for(int i= 0; i<networkMessageCommandList.getCommandCount(); ++i) { for(int i= 0; i<networkMessageCommandList.getCommandCount(); ++i) {
//serverInterface->requestCommand(networkMessageCommandList.getCommand(i)); //serverInterface->requestCommand(networkMessageCommandList.getCommand(i));
vctPendingNetworkCommandList.push_back(*networkMessageCommandList.getCommand(i)); vctPendingNetworkCommandList.push_back(*networkMessageCommandList.getCommand(i));

View File

@@ -104,6 +104,9 @@ private:
bool gotIntro; bool gotIntro;
vector<NetworkCommand> vctPendingNetworkCommandList; vector<NetworkCommand> vctPendingNetworkCommandList;
ConnectionSlotThread* slotThreadWorker; ConnectionSlotThread* slotThreadWorker;
int currentFrameCount;
int currentLagCount;
time_t lastReceiveCommandListTime;
public: public:
ConnectionSlot(ServerInterface* serverInterface, int playerIndex); ConnectionSlot(ServerInterface* serverInterface, int playerIndex);
@@ -139,6 +142,12 @@ public:
bool updateCompleted(); bool updateCompleted();
virtual void sendMessage(const NetworkMessage* networkMessage); virtual void sendMessage(const NetworkMessage* networkMessage);
int getCurrentFrameCount() const { return currentFrameCount; }
int getCurrentLagCount() const { return currentLagCount; }
void setCurrentLagCount(int value) { currentLagCount = value; }
time_t getLastReceiveCommandListTime() const { return lastReceiveCommandListTime; }
protected: protected:

View File

@@ -38,12 +38,17 @@ namespace Glest{ namespace Game{
//bool enabledThreadedClientCommandBroadcast = true; //bool enabledThreadedClientCommandBroadcast = true;
bool enabledThreadedClientCommandBroadcast = false; bool enabledThreadedClientCommandBroadcast = false;
// The maximum amount of network update iterations a client is allowed to fall behind
int maxFrameCountLagAllowed = 10;
ServerInterface::ServerInterface(){ ServerInterface::ServerInterface(){
gameHasBeenInitiated = false; gameHasBeenInitiated = false;
gameSettingsUpdateCount = 0; gameSettingsUpdateCount = 0;
currentFrameCount = 0;
enabledThreadedClientCommandBroadcast = Config::getInstance().getBool("EnableThreadedClientCommandBroadcast","false"); enabledThreadedClientCommandBroadcast = Config::getInstance().getBool("EnableThreadedClientCommandBroadcast","false");
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] enabledThreadedClientCommandBroadcast = %d\n",__FILE__,__FUNCTION__,__LINE__,enabledThreadedClientCommandBroadcast); maxFrameCountLagAllowed = Config::getInstance().getInt("MaxFrameCountLagAllowed",intToStr(maxFrameCountLagAllowed).c_str());
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] enabledThreadedClientCommandBroadcast = %d, maxFrameCountLagAllowed = %d\n",__FILE__,__FUNCTION__,__LINE__,enabledThreadedClientCommandBroadcast,maxFrameCountLagAllowed);
for(int i= 0; i<GameConstants::maxPlayers; ++i){ for(int i= 0; i<GameConstants::maxPlayers; ++i){
slots[i]= NULL; slots[i]= NULL;
@@ -199,6 +204,35 @@ void ServerInterface::updateSlot(ConnectionSlotEvent *event) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
} }
// Only call when client has just sent us data
bool ServerInterface::clientLagCheck(ConnectionSlot* connectionSlot) {
bool clientLagExceeded = false;
if(connectionSlot != NULL && connectionSlot->isConnected() == true) {
int clientLag = this->getCurrentFrameCount() - connectionSlot->getCurrentFrameCount();
int clientLagCount = (gameSettings.getNetworkFramePeriod() > 0 ? (clientLag / gameSettings.getNetworkFramePeriod()) : 0);
connectionSlot->setCurrentLagCount(clientLagCount);
if(this->getCurrentFrameCount() > 0) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] playerIndex = %d, clientLag = %d, clientLagCount = %d, this->getCurrentFrameCount() = %d, connectionSlot->getCurrentFrameCount() = %d\n",__FILE__,__FUNCTION__,__LINE__,connectionSlot->getPlayerIndex(),clientLag,clientLagCount,this->getCurrentFrameCount(),connectionSlot->getCurrentFrameCount());
}
// New lag check
if(maxFrameCountLagAllowed > 0 && clientLagCount > maxFrameCountLagAllowed) {
clientLagExceeded = true;
char szBuf[4096]="";
snprintf(szBuf,4095,"%s exceeded max allowed LAG count of %d, clientLag = %d, disconnecting client.",Config::getInstance().getString("NetPlayerName",Socket::getHostName().c_str()).c_str(),maxFrameCountLagAllowed,clientLagCount);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,szBuf);
string sMsg = szBuf;
sendTextMessage(sMsg,-1);
connectionSlot->close();
}
}
return clientLagExceeded;
}
void ServerInterface::update() { void ServerInterface::update() {
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); //SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
@@ -328,15 +362,23 @@ void ServerInterface::update() {
// Step #3 dispatch network commands to the pending list so that they are done in proper order // Step #3 dispatch network commands to the pending list so that they are done in proper order
for(int i= 0; i< GameConstants::maxPlayers; ++i) { for(int i= 0; i< GameConstants::maxPlayers; ++i) {
ConnectionSlot* connectionSlot= slots[i]; ConnectionSlot* connectionSlot= slots[i];
if(connectionSlot != NULL && connectionSlot->isConnected() == true && if(connectionSlot != NULL && connectionSlot->isConnected() == true) {
connectionSlot->getPendingNetworkCommandList().size() > 0) { if(connectionSlot->getPendingNetworkCommandList().size() > 0) {
vector<NetworkCommand> vctPendingNetworkCommandList = connectionSlot->getPendingNetworkCommandList(); // New lag check
bool clientLagExceeded = clientLagCheck(connectionSlot);
if(clientLagExceeded) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] slotIndex = %d, clientLagExceeded = %d\n",__FILE__,__FUNCTION__,__LINE__,i,clientLagExceeded);
}
else {
vector<NetworkCommand> vctPendingNetworkCommandList = connectionSlot->getPendingNetworkCommandList();
for(int idx = 0; idx < vctPendingNetworkCommandList.size(); ++idx) { for(int idx = 0; idx < vctPendingNetworkCommandList.size(); ++idx) {
NetworkCommand &cmd = vctPendingNetworkCommandList[idx]; NetworkCommand &cmd = vctPendingNetworkCommandList[idx];
this->requestCommand(&cmd); this->requestCommand(&cmd);
}
connectionSlot->clearPendingNetworkCommandList();
}
} }
connectionSlot->clearPendingNetworkCommandList();
} }
} }
@@ -414,6 +456,9 @@ void ServerInterface::updateKeyframe(int frameCount){
Chrono chrono; Chrono chrono;
chrono.start(); chrono.start();
currentFrameCount = frameCount;
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] currentFrameCount = %d\n",__FILE__,__FUNCTION__,__LINE__,currentFrameCount);
NetworkMessageCommandList networkMessageCommandList(frameCount); NetworkMessageCommandList networkMessageCommandList(frameCount);
//build command list, remove commands from requested and add to pending //build command list, remove commands from requested and add to pending
@@ -649,10 +694,11 @@ string ServerInterface::getNetworkStatus() {
if(connectionSlot!= NULL){ if(connectionSlot!= NULL){
if(connectionSlot->isConnected()){ if(connectionSlot->isConnected()){
int clientLagCount = connectionSlot->getCurrentLagCount();
int lastClientCommandListTimeLag = difftime(time(NULL),connectionSlot->getLastReceiveCommandListTime());
float pingTime = connectionSlot->getThreadedPingMS(connectionSlot->getIpAddress().c_str()); float pingTime = connectionSlot->getThreadedPingMS(connectionSlot->getIpAddress().c_str());
char szBuf[100]=""; char szBuf[100]="";
sprintf(szBuf,", ping = %.2fms",pingTime); sprintf(szBuf,", lag = %d [%d], ping = %.2fms",clientLagCount,lastClientCommandListTimeLag,pingTime);
str+= connectionSlot->getName() + string(szBuf); str+= connectionSlot->getName() + string(szBuf);
} }

View File

@@ -37,6 +37,7 @@ private:
int gameSettingsUpdateCount; int gameSettingsUpdateCount;
SwitchSetupRequest* switchSetupRequests[GameConstants::maxPlayers]; SwitchSetupRequest* switchSetupRequests[GameConstants::maxPlayers];
Mutex serverSynchAccessor; Mutex serverSynchAccessor;
int currentFrameCount;
//ConnectionSlotThread* slotThreads[GameConstants::maxPlayers]; //ConnectionSlotThread* slotThreads[GameConstants::maxPlayers];
@@ -78,6 +79,8 @@ public:
virtual void slotUpdateTask(ConnectionSlotEvent *event); virtual void slotUpdateTask(ConnectionSlotEvent *event);
bool hasClientConnection(); bool hasClientConnection();
int getCurrentFrameCount() const { return currentFrameCount; }
bool clientLagCheck(ConnectionSlot* connectionSlot);
public: public:

View File

@@ -1356,6 +1356,9 @@ BroadCastClientSocketThread::BroadCastClientSocketThread(DiscoveredServersInterf
void BroadCastClientSocketThread::execute() { void BroadCastClientSocketThread::execute() {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
setRunningStatus(true);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcast Client thread is running\n");
std::vector<string> foundServers; std::vector<string> foundServers;
short port; // The port for the broadcast. short port; // The port for the broadcast.
@@ -1396,9 +1399,6 @@ void BroadCastClientSocketThread::execute() {
Socket::setBlock(false, bcfd); Socket::setBlock(false, bcfd);
setRunningStatus(true);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcast Client thread is running\n");
try try
{ {
// Keep getting packets forever. // Keep getting packets forever.
@@ -1436,15 +1436,12 @@ void BroadCastClientSocketThread::execute() {
} }
catch(const exception &ex) { catch(const exception &ex) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what()); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
setRunningStatus(false); //setRunningStatus(false);
} }
catch(...) { catch(...) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] unknown error\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] unknown error\n",__FILE__,__FUNCTION__,__LINE__);
setRunningStatus(false); //setRunningStatus(false);
} }
setRunningStatus(false);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcast Client thread is exiting\n");
} }
#ifndef WIN32 #ifndef WIN32
@@ -1459,10 +1456,14 @@ void BroadCastClientSocketThread::execute() {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
setRunningStatus(false);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcast Client thread is exiting\n");
// Here we callback into the implementer class // Here we callback into the implementer class
if(discoveredServersCB != NULL) { if(discoveredServersCB != NULL) {
discoveredServersCB->DiscoveredServers(foundServers); discoveredServersCB->DiscoveredServers(foundServers);
} }
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
} }
@@ -1642,6 +1643,9 @@ void BroadCastSocketThread::execute() {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
setRunningStatus(true);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcast thread is running\n");
const int MAX_NIC_COUNT = 10; const int MAX_NIC_COUNT = 10;
short port; // The port for the broadcast. short port; // The port for the broadcast.
struct sockaddr_in bcLocal[MAX_NIC_COUNT]; // local socket address for the broadcast. struct sockaddr_in bcLocal[MAX_NIC_COUNT]; // local socket address for the broadcast.
@@ -1652,8 +1656,6 @@ void BroadCastSocketThread::execute() {
char myhostname[100]; // hostname of local machine char myhostname[100]; // hostname of local machine
char subnetmask[MAX_NIC_COUNT][100]; // Subnet mask to broadcast to char subnetmask[MAX_NIC_COUNT][100]; // Subnet mask to broadcast to
struct hostent* myhostent; struct hostent* myhostent;
//char * ptr; // some transient vars
//int len,i;
/* get my host name */ /* get my host name */
gethostname(myhostname,100); gethostname(myhostname,100);
@@ -1696,9 +1698,6 @@ void BroadCastSocketThread::execute() {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] setting up broadcast on address [%s]\n",__FILE__,__FUNCTION__,__LINE__,subnetmask[idx]); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] setting up broadcast on address [%s]\n",__FILE__,__FUNCTION__,__LINE__,subnetmask[idx]);
} }
setRunningStatus(true);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcast thread is running\n");
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
time_t elapsed = 0; time_t elapsed = 0;
@@ -1740,11 +1739,11 @@ void BroadCastSocketThread::execute() {
} }
catch(const exception &ex) { catch(const exception &ex) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what()); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
setRunningStatus(false); //setRunningStatus(false);
} }
catch(...) { catch(...) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] unknown error\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] unknown error\n",__FILE__,__FUNCTION__,__LINE__);
setRunningStatus(false); //setRunningStatus(false);
} }
} }