Added packet loss logic for multiple clients.

Changed packet class to fit our needs.
This commit is contained in:
Jocke
2016-01-20 13:43:11 +01:00
parent 85523343b2
commit f52cddb445
6 changed files with 58 additions and 28 deletions
+2 -1
View File
@@ -14,6 +14,7 @@ public:
Packet(MessageType type, unsigned int& packetID); Packet(MessageType type, unsigned int& packetID);
// Used to create packet from already existing data buffer. // Used to create packet from already existing data buffer.
Packet(char* data, const int sizeOfPacket); Packet(char* data, const int sizeOfPacket);
Packet(MessageType type);
~Packet(); ~Packet();
void Init(MessageType type, unsigned int& packetID); void Init(MessageType type, unsigned int& packetID);
@@ -49,7 +50,7 @@ public:
// Pops the first element as if it was a string. // Pops the first element as if it was a string.
std::string ReadString(); std::string ReadString();
char* ReadData(int SizeOfData); char* ReadData(int SizeOfData);
void ChangePacketID(unsigned int& packetID);
int Size() { return m_Offset; }; int Size() { return m_Offset; };
char* Data() { return m_Data; }; char* Data() { return m_Data; };
unsigned int DataReadSize() { return m_ReturnDataOffset; } unsigned int DataReadSize() { return m_ReturnDataOffset; }
@@ -6,6 +6,8 @@ struct PlayerDefinition {
int EntityID = -1; int EntityID = -1;
std::string Name = ""; std::string Name = "";
boost::asio::ip::udp::endpoint Endpoint; boost::asio::ip::udp::endpoint Endpoint;
unsigned int PacketID;
std::clock_t StopTime;
}; };
#endif #endif
+3 -5
View File
@@ -43,16 +43,14 @@ private:
//Timers //Timers
std::clock_t m_StartPingTime; std::clock_t m_StartPingTime;
std::clock_t m_StopTimes[8];
// Game logic // Game logic
World* m_World; World* m_World;
EventBroker* m_EventBroker; EventBroker* m_EventBroker;
// Packet loss logic // Packet loss logic
unsigned int m_PacketID; unsigned int m_PacketID = 0;
unsigned int m_PreviousPacketID; unsigned int m_PreviousPacketID = 0;
unsigned int m_SendPacketID;
// Private member functions // Private member functions
int receive(char* data, size_t length); int receive(char* data, size_t length);
@@ -73,8 +71,8 @@ private:
void parseServerPing(); void parseServerPing();
void identifyPacketLoss(); void identifyPacketLoss();
EntityID createPlayer(); EntityID createPlayer();
int GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint);
// Debug event // Debug event
EventRelay<Server, Events::InputCommand> m_EInputCommand; EventRelay<Server, Events::InputCommand> m_EInputCommand;
bool OnInputCommand(const Events::InputCommand& e); bool OnInputCommand(const Events::InputCommand& e);
}; };
+2 -4
View File
@@ -57,9 +57,7 @@ void Client::parseMessageType(Packet& packet)
// Read packet ID // Read packet ID
m_PreviousPacketID = m_PacketID; // Set previous packet id m_PreviousPacketID = m_PacketID; // Set previous packet id
m_PacketID = packet.ReadPrimitive<int>(); //Read new packet id m_PacketID = packet.ReadPrimitive<int>(); //Read new packet id
if (m_PacketID <= m_PreviousPacketID) identifyPacketLoss();
return;
//IdentifyPacketLoss();
switch (static_cast<MessageType>(messageType)) { switch (static_cast<MessageType>(messageType)) {
case MessageType::Connect: case MessageType::Connect:
@@ -282,7 +280,7 @@ void Client::identifyPacketLoss()
// if no packets lost, difference should be equal to 1 // if no packets lost, difference should be equal to 1
int difference = m_PacketID - m_PreviousPacketID; int difference = m_PacketID - m_PreviousPacketID;
if (difference != 1) { if (difference != 1) {
LOG_INFO("%i Packet(s) were lost...", difference); LOG_INFO("%i Packet(s) were lost...", difference -1);
} }
} }
+17 -4
View File
@@ -17,20 +17,26 @@ Packet::Packet(char* data, const int sizeOfPacket)
m_Offset = sizeOfPacket; m_Offset = sizeOfPacket;
} }
Packet::Packet(MessageType type)
{
m_Data = new char[m_MaxPacketSize];
unsigned int dummy = 0;
Init(type, dummy);
}
Packet::~Packet() Packet::~Packet()
{ {
delete[] m_Data; delete[] m_Data;
} }
void Packet::Init(MessageType type, unsigned int & packetID) void Packet::Init(MessageType type, unsigned int & packetID)
{ {
m_ReturnDataOffset = 0; m_ReturnDataOffset = 0;
m_Offset = 0; m_Offset = 0;
// Create message header // Create message header
// Add message type // Add message type
int messageType = static_cast<int>(type); int messageType = static_cast<int>(type);
Packet::WritePrimitive<int>(messageType); Packet::WritePrimitive<int>(messageType);
packetID = packetID % 1000; // Packet id modulos
Packet::WritePrimitive<int>(packetID); Packet::WritePrimitive<int>(packetID);
packetID++; packetID++;
} }
@@ -80,14 +86,21 @@ char * Packet::ReadData(int SizeOfData)
return (m_Data + oldReturnDataOffset); return (m_Data + oldReturnDataOffset);
} }
void Packet::ChangePacketID(unsigned int & packetID)
{
packetID = packetID + 1;
// Overwrite old PacketID
memcpy(m_Data + sizeof(int), &packetID, sizeof(int));
}
void Packet::resizeData() void Packet::resizeData()
{ {
// Allocate memory to store our data in // Allocate memory to store our data in
char* holdData = new char[m_MaxPacketSize]; char* holdData = new char[m_MaxPacketSize];
// Copy our data to the newly allocated memory // Copy our data to the newly allocated memory
memcpy(holdData, m_Data, m_Offset); memcpy(holdData, m_Data, m_Offset);
// Increase max packet size // Increase max packet size
m_MaxPacketSize = m_MaxPacketSize * 2; m_MaxPacketSize = m_MaxPacketSize * 2;
// Delete our data // Delete our data
delete m_Data; delete m_Data;
+32 -14
View File
@@ -16,7 +16,7 @@ void Server::Start(World* world, EventBroker* eventBroker)
// Subscribe to events // Subscribe to events
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Server::OnInputCommand); EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Server::OnInputCommand);
for (size_t i = 0; i < MAXCONNECTIONS; i++) { for (size_t i = 0; i < MAXCONNECTIONS; i++) {
m_StopTimes[i] = std::clock(); m_PlayerDefinitions[i].StopTime = std::clock();
} }
LOG_INFO("I am Server. BIP BOP\n"); LOG_INFO("I am Server. BIP BOP\n");
} }
@@ -66,7 +66,7 @@ void Server::parseMessageType(Packet& packet)
// Read packet ID // Read packet ID
m_PreviousPacketID = m_PacketID; // Set previous packet id m_PreviousPacketID = m_PacketID; // Set previous packet id
m_PacketID = packet.ReadPrimitive<int>(); //Read new packet id m_PacketID = packet.ReadPrimitive<int>(); //Read new packet id
//IdentifyPacketLoss(); //identifyPacketLoss();
switch (static_cast<MessageType>(messageType)) { switch (static_cast<MessageType>(messageType)) {
case MessageType::Connect: case MessageType::Connect:
parseConnect(packet); parseConnect(packet);
@@ -126,6 +126,7 @@ void Server::broadcast(Packet& packet)
{ {
for (int i = 0; i < MAXCONNECTIONS; ++i) { for (int i = 0; i < MAXCONNECTIONS; ++i) {
if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) {
packet.ChangePacketID(m_PlayerDefinitions[i].PacketID);
send(packet, i); send(packet, i);
} }
} }
@@ -137,7 +138,7 @@ void Server::sendSnapshot()
// Should time this // Should time this
std::unordered_map<std::string, ComponentPool*> worldComponentPools = m_World->GetComponentPools(); std::unordered_map<std::string, ComponentPool*> worldComponentPools = m_World->GetComponentPools();
for (auto& it : worldComponentPools) { for (auto& it : worldComponentPools) {
Packet packet(MessageType::Snapshot, m_SendPacketID); Packet packet(MessageType::Snapshot);
ComponentPool* componentPool = it.second; ComponentPool* componentPool = it.second;
ComponentInfo componentInfo = componentPool->ComponentInfo(); ComponentInfo componentInfo = componentPool->ComponentInfo();
// Component Type // Component Type
@@ -166,12 +167,12 @@ void Server::sendPing()
// Prints connected players ping // Prints connected players ping
for (size_t i = 0; i < MAXCONNECTIONS; i++) { for (size_t i = 0; i < MAXCONNECTIONS; i++) {
if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) {
int ping = 1000 * (m_StopTimes[i] - m_StartPingTime) / static_cast<double>(CLOCKS_PER_SEC); int ping = 1000 * (m_PlayerDefinitions[i].StopTime - m_StartPingTime) / static_cast<double>(CLOCKS_PER_SEC);
LOG_INFO("Last packetID received %i: Player %i's ping: %i", m_PacketID, i, ping); LOG_INFO("Last packetID received %i: Player %i's ping: %i", m_PlayerDefinitions[i].PacketID, i, ping);
} }
} }
// Create ping message // Create ping message
Packet packet(MessageType::ServerPing, m_SendPacketID); Packet packet(MessageType::ServerPing);
packet.WriteString("Ping from server"); packet.WriteString("Ping from server");
// Time message // Time message
m_StartPingTime = std::clock(); m_StartPingTime = std::clock();
@@ -187,8 +188,8 @@ void Server::checkForTimeOuts()
for (size_t i = 0; i < MAXCONNECTIONS; i++) { for (size_t i = 0; i < MAXCONNECTIONS; i++) {
if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) {
int stopPing = 1000 * m_StopTimes[i] int stopPing = 1000 * m_PlayerDefinitions[i].StopTime /
/ static_cast<double>(CLOCKS_PER_SEC); static_cast<double>(CLOCKS_PER_SEC);
if (startPing > stopPing + timeOutTimeMs) { if (startPing > stopPing + timeOutTimeMs) {
LOG_INFO("Player %i timed out!", i); LOG_INFO("Player %i timed out!", i);
disconnect(i); disconnect(i);
@@ -206,6 +207,7 @@ void Server::disconnect(int i)
m_PlayerDefinitions[i].Endpoint = boost::asio::ip::udp::endpoint(); m_PlayerDefinitions[i].Endpoint = boost::asio::ip::udp::endpoint();
m_PlayerDefinitions[i].EntityID = -1; m_PlayerDefinitions[i].EntityID = -1;
m_PlayerDefinitions[i].Name = ""; m_PlayerDefinitions[i].Name = "";
m_PlayerDefinitions[i].PacketID = 0;
} }
void Server::parseOnInputCommand(Packet& packet) void Server::parseOnInputCommand(Packet& packet)
@@ -259,19 +261,20 @@ void Server::parseConnect(Packet& packet)
m_PlayerDefinitions[i].EntityID = createPlayer(); m_PlayerDefinitions[i].EntityID = createPlayer();
m_PlayerDefinitions[i].Endpoint = m_ReceiverEndpoint; m_PlayerDefinitions[i].Endpoint = m_ReceiverEndpoint;
m_PlayerDefinitions[i].Name = packet.ReadString(); m_PlayerDefinitions[i].Name = packet.ReadString();
m_PlayerDefinitions[i].PacketID = 0;
m_StopTimes[i] = std::clock(); m_PlayerDefinitions[i].StopTime = std::clock();
LOG_INFO("Player \"%s\" connected on IP: %s", m_PlayerDefinitions[i].Name.c_str(), m_PlayerDefinitions[i].Endpoint.address().to_string().c_str()); LOG_INFO("Player \"%s\" connected on IP: %s", m_PlayerDefinitions[i].Name.c_str(), m_PlayerDefinitions[i].Endpoint.address().to_string().c_str());
// Send a message to the player that connected // Send a message to the player that connected
Packet packet(MessageType::Connect, m_SendPacketID); Packet packet(MessageType::Connect, m_PlayerDefinitions[i].PacketID);
packet.WritePrimitive<int>(i); // Player ID packet.WritePrimitive<int>(i); // Player ID
packet.WritePrimitive<EntityID>(m_PlayerDefinitions[i].EntityID); // Entity ID packet.WritePrimitive<EntityID>(m_PlayerDefinitions[i].EntityID); // Entity ID
send(packet, i); send(packet, i);
// Send notification that a player has connected // Send notification that a player has connected
Packet notificationPacket(MessageType::PlayerConnected, m_PacketID); Packet notificationPacket(MessageType::PlayerConnected);
broadcast(notificationPacket); broadcast(notificationPacket);
break; break;
@@ -294,17 +297,21 @@ void Server::parseDisconnect()
void Server::parseClientPing() void Server::parseClientPing()
{ {
LOG_INFO("%i: Parsing ping", m_PacketID); LOG_INFO("%i: Parsing ping", m_PacketID);
int playerID = GetPlayerIDFromEndpoint(m_ReceiverEndpoint);
if (playerID == -1) {
return;
}
// Return ping // Return ping
Packet packet(MessageType::ClientPing, m_SendPacketID); Packet packet(MessageType::ClientPing, m_PlayerDefinitions[playerID].PacketID);
packet.WriteString("Ping received"); packet.WriteString("Ping received");
send(packet); // This dosen't work for multiple users send(packet);
} }
void Server::parseServerPing() void Server::parseServerPing()
{ {
for (int i = 0; i < MAXCONNECTIONS; i++) { for (int i = 0; i < MAXCONNECTIONS; i++) {
if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()) { if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()) {
m_StopTimes[i] = std::clock(); m_PlayerDefinitions[i].StopTime = std::clock();
break; break;
} }
} }
@@ -331,6 +338,17 @@ EntityID Server::createPlayer()
return entityID; return entityID;
} }
int Server::GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint)
{
for (int i = 0; i < MAXCONNECTIONS; i++) {
if (m_PlayerDefinitions[i].Endpoint.address() == endpoint.address() &&
m_PlayerDefinitions[i].Endpoint.port() == endpoint.port()) {
return i;
}
}
return -1;
}
bool Server::OnInputCommand(const Events::InputCommand & e) bool Server::OnInputCommand(const Events::InputCommand & e)
{ {
//LOG_INFO("Server::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); //LOG_INFO("Server::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID);