Note: I am mixing some C & C++ but it shouldn’t be too confusing.
Connected clients are added to a multimap (might aswel have been a map, I know ^^).
The multimap
typedef std::multimap<std::string, SOCKET> clientMap;
typedef std::pair<clientMap::iterator,
clientMap::iterator>
clientIters;
clientMap clientmap;
clientIters clientByID(std::string clientID)
{
return clientmap.equal_range(clientID);
}
Adding a client (each client runs in it’s own thread)
//Add clientID to map of clients
if(clientAdded == false)
{
std::stringstream ss;
ss << lpParam; //Use socket# as the unique ID
clientID = ss.str();
clientmap.insert(std::pair<std::string,SOCKET>(clientID,sock));
clientAdded = true;
}
//Client wasn't added correctly!
if(clientID == "" || clientAdded == false)
{
std::cout << "Problem adding client" << std::endl;
}
Server waits for client messages with a blocking recv() call
ret = recv(sock, szBuff, DEFAULT_BUFFER, 0);
if (ret == 0) // Graceful close
break;
else if (ret == SOCKET_ERROR)
{
printf("recv() failed: %d\n", WSAGetLastError());
removeUser(clientID);
break;
}
removeUser() function
void removeUser(std::string clientID)
{
std::cout << "Going to try and remove client: " << clientID << std::endl;
//Remove client
clientIters iters = clientByID(clientID);
clientMap::iterator it = iters.first;
while(it != iters.second)
{
clientmap.erase(it++);
std::cout << "removed client: " << it->first << std::endl;
}
//Show remaining clients
std::cout << "clients left:" << std::endl;
for (clientMap::iterator it = clientmap.begin(); it != clientmap.end(); ++it)
{
std::cout << it->first << std::endl;
}
}
All of this is working fine if I close a client that was connected to either my local IP or external IP (directly).
recv() failed: 10054
Going to try and remove client 0000008C
removed client 0000008C
clients left:
00000084
00000088
But if I put a proxy inbetween (using proxifier), the server thinks the connection is still active or something because the server doesn’t do anything when I close the client. It just sits there.. waiting for nothing.
I’m using this socket class as a base but it’s pretty heavily modified by now.
How can I make sure a closed client is definitely removed from the multimap?
Could you store some state for each connection? like the last time something was received?
You could then periodically loop through your active connections and prune any that haven’t sent anything for a long time, as the connection is more then likely stale.