OverviewOk, sorry to bug you guys and make a new thread, but I feel that the other one was titled wrongly for what I' now encountering.
The server is now stable thanks to Binary's help, but my client is very unstable. Again, I cannot replicate any of the crashes myself, which leads me to believe that
people who live further away (with greater ping times) are corrupting the packets somehow. I don't know how this is possible, but it's crippling the stability of my playerbase and I have absolutely no way of testing it.
Details:I am using unblocking TCP sockets, although I switch to blocking when I connect() from the client.CodeServer send code:void NetworkManager::sendPacket(sf::Packet* pack, sf::Int32 connectorID, bool delPacket)
{
if(getConnectorWithID(connectorID) != NULL)
{
Connector* c = getConnectorWithID(connectorID);
if(c != NULL)
c->sendPacket(pack);
}
if(delPacket)
{
//sf::Int32 packID;
//*pack >> packID;
//std::cout << "Sending :: " << packID << "\n";
delete pack;
}
}
Retry send if it fails or returns sf::Socket::NotReady:void NetworkManager::retryDroppedPackets()
{
for(sf::Int32 i = 0; i < ent::connectors.size(); i++)
{
if(ent::connectors[i]->packets.size() > 0)
{
sf::Socket::Status status = ent::connectors[i]->socket.send(ent::connectors[i]->packets.front());
if(status != sf::Socket::NotReady && status != sf::Socket::Error)
{
ent::connectors[i]->packets.pop();
if(status == sf::Socket::Error)
{
std::cout << "E1E\n";
}
}
}
}
}
Server receive code:void NetworkManager::recPackets()
{
Connector* newConnector = new Connector;
newConnector->socket.setBlocking(false);
newConnector->player = NULL;
if(listener.accept(newConnector->socket) == sf::Socket::Done)
{
// Adds a new client to client list
maxConID += 1;
newConnector->setID(maxConID);
ent::connectors.push_back(newConnector);
}
else
{
// Nothing we can do...
delete newConnector;
}
// The listener socket is not ready, test all other sockets
for(sf::Int32 i = 0; i < ent::connectors.size(); i++)
{
sf::Packet packet;
sf::Socket::Status status = ent::connectors[i]->socket.receive(packet);
if(status == sf::Socket::Done)
{
ent::connectors[i]->logClock.restart();
sf::Uint32 packetCode;
packet >> packetCode;
handlePacket(packetCode, packet, ent::connectors[i]->getID());
}
else if(status == sf::Socket::Disconnected)
{
ent::playerHandler.handleDisconnect(ent::connectors[i]->getID());
}
else if(status == sf::Socket::Error)
{
std::cout << "NetworkingError";
}
else if(status == sf::Socket::NotReady)
{
// Not ready
//std::cout << "not ready";
}
}
}
Client send code:void NetworkManager::sendPacket(sf::Packet* pack)
{
socket.setBlocking(false);
if(droppedPackets.size() <= 0)
{
sf::Socket::Status status = socket.send(*pack);
if(status == sf::Socket::Done)
{
delete pack;
}
else if(status == sf::Socket::NotReady)
{
droppedPackets.push(pack);
}
else if(status == sf::Socket::Error)
{
std::cout << "ERROR";
droppedPackets.push(pack);
}
else if(status == sf::Socket::Disconnected)
{
if(ent::game.isRunning())
{
ent::game.disconnect();
delete pack;
}
}
}
else
{
droppedPackets.push(pack);
}
}
Server send code if first time fails:void NetworkManager::retryPackets()
{
if(droppedPackets.size() > 0)
{
socket.setBlocking(false);
sf::Socket::Status status = socket.send(*droppedPackets.front());
if(status == sf::Socket::Done)
{
delete droppedPackets.front();
droppedPackets.pop();
}
else if(status == sf::Socket::NotReady)
{
// Do nothing
}
else if(status == sf::Socket::Error)
{
std::cout << "ERROR";
delete droppedPackets.front();
droppedPackets.pop();
}
else if(status == sf::Socket::Disconnected)
{
if(ent::game.isRunning())
{
ent::game.disconnect();
delete droppedPackets.front();
droppedPackets.pop();
}
}
}
}
Client receive:void NetworkManager::handle()
{
retryPackets();
socket.setBlocking(false);
sf::Packet pack;
sf::Socket::Status status = socket.receive(pack);
if(status == sf::Socket::Done)
{
sf::Int32 packetType; // Determines what the packet contains, different packet types contain different info
if(pack >> packetType)
{
if(displayPacketID)
std::cout << "\nPacket Type :: " << packetType;
//
//
// Handle Packet
//
//
}
else
{
if(displayPacketID)
std::cout << "Junk Packet";
}
}
else
{
// not ready
}
}
Client connect code (runs on its own thread):bool NetworkManager::connect(std::string IP, sf::Int32 port)
{
if(ip != NULL)
delete ip;
ip = new sf::IpAddress(IP);
socket.setBlocking(true);
sf::Socket::Status status = socket.connect(*ip, port, sf::milliseconds(250));
socket.setBlocking(false);
if(status == sf::Socket::Disconnected)
{
//std::cout << "disconnected";
connected = false;
gl::Vars::connected = false;
return false;
}
else if(status == sf::Socket::Done)
{
//std::cout << "connected";
gl::Vars::connected = true;
connected = true;
sf::Packet* spack = new sf::Packet;
sf::Int32 packID = 0;
*spack << packID << gl::Vars::versionNumber;
ent::networkManager.sendPacket(spack);
return true;
}
else if(status == sf::Socket::Error)
{
connected = false;
gl::Vars::connected = false;
return false;
}
else
{
std::cout << "not ready";
connected = false;
gl::Vars::connected = false;
return false;
}
}
Client Main:ent::menu.Run();
if(ent::menu.getSuccess()) // If logged in
{
ent::loadingScreen.Run();
if(ent::game.Run()) // if dead
{
ent::death.Run();
}
}
Game.Run()Init();
cleanClock.restart();
while(running && !dead)
{
ent::networkManager.handle();
Input();
Data();
Clear();
Draw();
if(cleanClock.getElapsedTime().asSeconds() >= 10.0f)
{
cleanClock.restart();
Clean();
}
}
cleanUp();
return dead;
I'd love if one of you veterans could add me on Skype (brady.welch) so we can resolve this issue. I could send you the full source and client for you to test for my game.