How to delete Inactive Client

Started by
14 comments, last by Tano_ITA 15 years, 4 months ago
Hi, i've a STL::MAP with all client connected to my server. And i've a sub-structure called "ClientGroup" (a Room where all player can chat). I need to delete inactive client. For example, when a client crash, i can't read a disconnect message from him, so i need to delete it when he is gone. I've tried to create a method like this:

void SystemServer::sendMessageControlToAllClient()
{
	map<SOCKET, Client*>::iterator itl;
	string	buf = "a";
	bool	cicla = true;
	int iStat;
	string tempNickname;

	while(cicla)
	{
		for(itl = CServerObj.ClientMap.begin(); itl != CServerObj.ClientMap.end(); ++itl)
		{
			cicla = false;
			iStat = send((*itl).first, buf.c_str(),buf.size(), 0);

			if(iStat == -1)
			{
				Client *client = CServerObj.ClientMap[(*itl).first];
				if(client->getGroup() == NULL)
				{
					CServerObj.removeClientFromMap((*itl).first);
					CServerObj.m_numClient--;
				}
				else
				{
					tempNickname = client->getGroup()->getNickNameFromGroup((*itl).first);
					client->getGroup()->removeClient(client->getGroup()->getNickNameFromGroup((*itl).first));
					//client->getGroup()->deleteInactiveClient();
					CServerObj.removeClientFromMap((*itl).first, tempNickname);
					CServerObj.m_numClientConnectedToAGroup--;
					CServerObj.m_numClient--;
				}
				cicla = true;
				break;
				
			}
		}
		if(CServerObj.ClientMap.size() == 0)
			cicla = false;
	}
	

}
but this method is really expensive. I want create e "Timer" for each client connected, when a timer is finished, i delete this client. Anyone have another idea or another tecnique to solve this problem? Thanks a lot and sorry for my bad english!
Advertisement
I'm using C++, winsock and TCP/IP protocol.
I found a solution! I send always a message to all client when he chat. So i can use che send() method to see if the client respond. So i can do like this:

iStat = send((*itl).first, buf.c_str(),buf.size(), 0); 


iStat is an Int. So if iStat = -1 i can catch the Error with WSAGetLastError ( http://msdn.microsoft.com/en-us/library/ms740149(VS.85).aspx ). So now i try this solution, but i need suggest anyway =).

Thanks!
1° Require all clients to send you a message every 10 seconds [or whatever amount of time you wish]. If the user types nothing, just send an empty "I'm still here" message.

2° Whenever you receive a message from a client, store the time.

3° When you want to clean up disconnections, check the "last received message" time of every client and, if it's older than 10 seconds, disconnect the client.
Are you using select() to see which sockets have something to read from?

If so, finding out when a client has disconnected is pretty easy (when TCP/IP is used).

while (running){	select(...);	for (all sockets)	{		if (FD_ISSET(socket, ...))		{			bytes_received = recv(socket, ...);			if (bytes_received < 0) { /* hard disconnect */ }			else if (bytes_received == 0) { /* graceful disconnect */ }			else if (bytes_received > 0) { /* received some data from this socket */ }		}	}	}


You can also use select to check which sockets have errors (exceptions) on them, which might also be a good idea.

I use the above and it seems to work pretty well.

The only problem that I know of is when a client doesn't communicate for a long time, the underlying TCP connection seems to silently time out and the server doesn't realize the client has disconnected. This can probably be solved by checking sockets for exceptions using the select statement (I don't do that yet), or by sending keep-alive TCP packets every minute or so (at least). Other than that, it's flawless.
To time out idle clients, you should store the client pointers sorted by last time data received, in a priority queue or map of some sort. That way, you don't have to scan through all clients to find the clients that are old; you can scan from the oldest, and stop as soon as you find one that's not old enough to disconnect.
enum Bool { True, False, FileNotFound };
Thanks for suggests, but i've another question: I'm using a blocking socket and i've a thread to listen socket recv(). So when the connection with a peer goes down, i recive always a "-1" (and i use WSAGetLastError() to see this error). So, i catch the "-1" and i shutdown the connection and delete the client from my clientMap. Without using a timeout. So, i need to know what are the disadvantages in this tecnique.

thanks.
Quote:Original post by Tano_ITA
So when the connection with a peer goes down, i recive always a "-1" (and i use WSAGetLastError() to see this error).
One cannot distinguish between a disconnected client and a client with a slow connection. Someone has to decide that clients that take longer than X to respond are seen as disconnected: if you don't, then someone else has for you—which means you might not know what X is.

  • Client A is connected to your server. All of a sudden, his router is clogged and any message you send him takes one entire minute to go through and reach him (but the messages are still received).
  • Client B is also connected to your server. All of a sudden, his router crashes and doesn't forward messages to him anymore (so he's disconnected).


Your computer sends a message to both clients. After one minute, it still hasn't received a response from either A or B, which means it does not know who is who. Does it keep both clients as "connected" or does it disconnect both?
With a thread per client, you will choke the server at some point. Each thread has significant overhead in the kernel scheduler, for the thread stack, for context, etc.
enum Bool { True, False, FileNotFound };
So, the best way is using IOCP right?

This topic is closed to new replies.

Advertisement