- added client side ping style packet for linux socket disconnect checking

This commit is contained in:
Mark Vejvoda 2010-07-09 15:01:49 +00:00
parent 4ba69753f9
commit 3e53b69676
11 changed files with 127 additions and 35 deletions

View File

@ -48,6 +48,8 @@ struct FormatString {
MenuStateConnectedGame::MenuStateConnectedGame(Program *program, MainMenu *mainMenu,JoinMenu joinMenuInfo, bool openNetworkSlots):
MenuState(program, mainMenu, "connected-game") //← set on connected-game
{
lastNetworkSend = time(NULL);
returnMenuInfo=joinMenuInfo;
Lang &lang= Lang::getInstance();
NetworkManager &networkManager= NetworkManager::getInstance();
@ -360,6 +362,12 @@ void MenuStateConnectedGame::update()
ClientInterface* clientInterface= NetworkManager::getInstance().getClientInterface();
Lang &lang= Lang::getInstance();
const int pingFrequency = 5;
if(difftime(time(NULL),lastNetworkSend) >= pingFrequency) {
lastNetworkSend = time(NULL);
clientInterface->sendPingMessage(pingFrequency, time(NULL));
}
//update status label
if(clientInterface != NULL && clientInterface->isConnected()) {
buttonDisconnect.setText(lang.get("Disconnect"));

View File

@ -71,6 +71,7 @@ private:
string currentMap;
JoinMenu returnMenuInfo;
bool settingsReceivedFromServer;
time_t lastNetworkSend;
public:

View File

@ -266,6 +266,17 @@ void ClientInterface::updateLobby()
}
break;
case nmtPing:
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtPing\n",__FILE__,__FUNCTION__);
NetworkMessagePing networkMessagePing;
if(receiveMessage(&networkMessagePing)) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
}
break;
case nmtSynchNetworkGameData:
{
NetworkMessageSynchNetworkGameData networkMessageSynchNetworkGameData;
@ -540,6 +551,17 @@ void ClientInterface::updateKeyframe(int frameCount)
}
break;
case nmtPing:
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtPing\n",__FILE__,__FUNCTION__);
NetworkMessagePing networkMessagePing;
if(receiveMessage(&networkMessagePing)) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
}
break;
case nmtQuit:
{
NetworkMessageQuit networkMessageQuit;
@ -746,6 +768,11 @@ void ClientInterface::sendTextMessage(const string &text, int teamIndex, bool ec
}
void ClientInterface::sendPingMessage(int32 pingFrequency, int64 pingTime) {
NetworkMessagePing networkMessagePing(pingFrequency,pingTime);
sendMessage(&networkMessagePing);
}
string ClientInterface::getNetworkStatus() {
std::string label = Lang::getInstance().get("Server") + ": " + serverName;
//float pingTime = getThreadedPingMS(getServerIpAddress().c_str());
@ -866,6 +893,13 @@ bool ClientInterface::shouldDiscardNetworkMessage(NetworkMessageType networkMess
this->receiveMessage(&msg);
}
break;
case nmtPing:
{
discard = true;
NetworkMessagePing msg = NetworkMessagePing();
this->receiveMessage(&msg);
}
break;
case nmtLaunch:
{
discard = true;

View File

@ -94,6 +94,8 @@ public:
int getCurrentFrameCount() const { return currentFrameCount; }
virtual void sendPingMessage(int32 pingFrequency, int64 pingTime);
protected:
Mutex * getServerSynchAccessor() { return NULL; }

View File

@ -170,11 +170,6 @@ ConnectionSlot::ConnectionSlot(ServerInterface* serverInterface, int playerIndex
networkGameDataSynchCheckOkMap = false;
networkGameDataSynchCheckOkTile = false;
networkGameDataSynchCheckOkTech = false;
//networkGameDataSynchCheckOkFogOfWar = false;
//chatText.clear();
//chatSender.clear();
//chatTeamIndex= -1;
this->clearChatInfo();
}
@ -229,9 +224,6 @@ void ConnectionSlot::update(bool checkForNewClients) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] accepted new client connection, serverInterface->getOpenSlotCount() = %d\n",__FILE__,__FUNCTION__,serverInterface->getOpenSlotCount());
connectedTime = time(NULL);
//chatText.clear();
//chatSender.clear();
//chatTeamIndex= -1;
this->clearChatInfo();
if(hasOpenSlots == false) {
@ -255,9 +247,6 @@ void ConnectionSlot::update(bool checkForNewClients) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(socket->isConnected()) {
//chatText.clear();
//chatSender.clear();
//chatTeamIndex= -1;
this->clearChatInfo();
if(socket->hasDataToRead() == true) {
@ -272,16 +261,23 @@ void ConnectionSlot::update(bool checkForNewClients) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] got nmtInvalid\n",__FILE__,__FUNCTION__,__LINE__);
break;
case nmtPing:
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtPing\n",__FILE__,__FUNCTION__);
NetworkMessagePing networkMessagePing;
if(receiveMessage(&networkMessagePing)) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
}
break;
case nmtText:
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtText\n",__FILE__,__FUNCTION__);
NetworkMessageText networkMessageText;
if(receiveMessage(&networkMessageText)) {
//chatText = networkMessageText.getText();
//chatSender = networkMessageText.getSender();
//chatTeamIndex = networkMessageText.getTeamIndex();
ChatMsgInfo msg(networkMessageText.getText().c_str(),networkMessageText.getSender().c_str(),networkMessageText.getTeamIndex());
this->addChatInfo(msg);

View File

@ -32,7 +32,7 @@ namespace Glest{ namespace Game{
// class NetworkInterface
// =====================================================
const int NetworkInterface::readyWaitTimeout= 120000; // 2 minutes
const int NetworkInterface::readyWaitTimeout= 180000; // 3 minutes
bool NetworkInterface::allowGameDataSynchCheck = false;
bool NetworkInterface::allowDownloadDataSynch = false;

View File

@ -141,6 +141,29 @@ void NetworkMessageIntro::send(Socket* socket) const{
NetworkMessage::send(socket, &data, sizeof(data));
}
// =====================================================
// class NetworkMessagePing
// =====================================================
NetworkMessagePing::NetworkMessagePing(){
data.messageType= nmtPing;
}
NetworkMessagePing::NetworkMessagePing(int32 pingFrequency, int64 pingTime){
data.messageType= nmtPing;
data.pingFrequency= pingFrequency;
data.pingTime= pingTime;
}
bool NetworkMessagePing::receive(Socket* socket){
return NetworkMessage::receive(socket, &data, sizeof(data));
}
void NetworkMessagePing::send(Socket* socket) const{
assert(data.messageType==nmtPing);
NetworkMessage::send(socket, &data, sizeof(data));
}
// =====================================================
// class NetworkMessageReady
// =====================================================

View File

@ -106,10 +106,38 @@ public:
virtual void send(Socket* socket) const;
};
// =====================================================
// class NetworkMessagePing
//
// Message sent at any time
// =====================================================
class NetworkMessagePing: public NetworkMessage{
private:
struct Data{
int8 messageType;
int32 pingFrequency;
int64 pingTime;
};
private:
Data data;
public:
NetworkMessagePing();
NetworkMessagePing(int32 pingFrequency, int64 pingTime);
int32 getPingFrequency() const {return data.pingFrequency;}
int64 getPingTime() const {return data.pingTime;}
virtual bool receive(Socket* socket);
virtual void send(Socket* socket) const;
};
// =====================================================
// class NetworkMessageReady
//
// Message sent at the beggining of the game
// Message sent at the beginning of the game
// =====================================================
class NetworkMessageReady: public NetworkMessage{

View File

@ -567,6 +567,7 @@ void ServerInterface::update() {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
//process text messages
/*
if(this->getChatTextList().empty() == true) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
@ -607,6 +608,7 @@ void ServerInterface::update() {
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
*/
}
}
}
@ -683,6 +685,14 @@ bool ServerInterface::shouldDiscardNetworkMessage(NetworkMessageType networkMess
connectionSlot->receiveMessage(&msg);
}
break;
case nmtPing:
{
discard = true;
NetworkMessagePing msg = NetworkMessagePing();
connectionSlot->receiveMessage(&msg);
}
break;
case nmtLaunch:
{
discard = true;

View File

@ -117,7 +117,7 @@ public:
PLATFORM_SOCKET getSocketId() const { return sock; }
int getDataToRead();
int getDataToRead(bool wantImmediateReply=false);
int send(const void *data, int dataSize);
int receive(void *data, int dataSize);
int peek(void *data, int dataSize);

View File

@ -696,8 +696,7 @@ Socket::Socket()
{
this->pingThread = NULL;
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(isSocketValid() == false)
{
if(isSocketValid() == false) {
throwException("Error creating socket");
}
}
@ -877,7 +876,7 @@ bool Socket::hasDataToRead(PLATFORM_SOCKET socket)
return bResult;
}
int Socket::getDataToRead(){
int Socket::getDataToRead(bool wantImmediateReply) {
unsigned long size = 0;
//fd_set rfds;
@ -927,6 +926,10 @@ int Socket::getDataToRead(){
break;
}
if(wantImmediateReply == true) {
break;
}
loopCount++;
}
}
@ -1091,7 +1094,6 @@ bool Socket::isReadable() {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s] error while selecting socket data, err = %d, error = %s\n",__FILE__,__FUNCTION__,i,getLastSocketErrorFormattedText().c_str());
}
}
//return (i == 1 && FD_ISSET(sock, &set));
bool result = (i == 1);
return result;
}
@ -1153,24 +1155,12 @@ bool Socket::isConnected() {
//if the socket is readable it is connected if we can read a byte from it
if(isReadable()) {
char tmp;
int err = peek(&tmp, sizeof(tmp));
int err = peek(&tmp, 1);
if(err <= 0) {
return false;
}
}
#ifndef WIN32
// Need this extra check for proper linux disconnect checking
struct sockaddr name;
socklen_t namelen = sizeof (name);
int peer_result = getpeername(sock, &name, &namelen);
if(peer_result != 0) {
return false;
}
#endif
//otherwise the socket is connected
return true;
}