Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: SFML Network buffer question  (Read 6268 times)

0 Members and 1 Guest are viewing this topic.

fredrick

  • Newbie
  • *
  • Posts: 20
    • View Profile
SFML Network buffer question
« on: January 22, 2010, 08:30:25 am »
While writing my library around SFML i found a design flaw on my end i guess. While debugging on localhost without any delay between server \ client i cant send multiple packets to the server (I'm using the selector).

Temporary solution was to add a delay in the code when server\client sent a packet so the other side got time to process it.

My question is, does SFML buffer these packets trough the selector somehow, because the server has no problems processing multiple clients yet the client side(that has no selector) in my case has this problem.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
SFML Network buffer question
« Reply #1 on: January 22, 2010, 08:35:57 am »
Can you show the relevant server code?
Laurent Gomila - SFML developer

fredrick

  • Newbie
  • *
  • Posts: 20
    • View Profile
SFML Network buffer question
« Reply #2 on: January 22, 2010, 09:19:07 am »
Server:

Code: [Select]

bool CTCPServer::ServerLoop()
{
bool ret = false;
m_online = true;

sf::SelectorTCP * serverSelector = (sf::SelectorTCP*)m_selector;
sf::SocketTCP * serverSocket = (sf::SocketTCP*)(m_socket);

if(serverSelector && serverSocket)
{
// Add the listener
serverSelector->Add(*serverSocket);

while(m_online)
{
// Get the sockets ready for reading
unsigned int NbSockets = serverSelector->Wait();

// We can read from each returned socket
for (unsigned int i = 0; i < NbSockets; ++i)
{
// Get the current socket
sf::SocketTCP socket = serverSelector->GetSocketReady(i);

if (socket == *serverSocket)
{
if(m_clients.size() < TCP_MAX_CLIENTS)
{
// If the listening socket is ready, it means that we can accept a new connection
sf::IPAddress *address = new sf::IPAddress;
sf::SocketTCP *client  = new sf::SocketTCP;

serverSocket->Accept(*client, address);

// Add it to the selector
serverSelector->Add(*client);
// Add it to our internal list
AddClient(address, client);
}
else
{
PrintLog(TCP_EVENT, "Client limit(%d) reached", TCP_MAX_CLIENTS);
}
}
else
{
// Else, it is a client socket so we can read the data he sent
char buffer[TCP_MAX_SIZE] = "";
size_t recievedSize = 0;
if (socket.Receive(buffer, TCP_MAX_SIZE, recievedSize) == sf::Socket::Done)
{
size_t clientId = GetClientId(&socket);
if(clientId < TCP_MAX_CLIENTS)
{
if(HandleInternalMessage(clientId, buffer, recievedSize) == false ||
  (m_forwardInternalMessage == true))
{
// This is not a internal message, push it forward to callback function.
(*TCPServerClientRecieveCallback)(clientId, buffer, recievedSize);
}
}
}
else
{
// Error : we'd better remove the socket from the selector
RemoveClient(GetClientId(&socket), DISCONNECT_SHUTDOWN);
}
}
}
}
}
else
{
PrintLog(TCP_ERROR, "%s Memory error", AT);
}
serverSocket->Close();
return ret;
}



Client:


Code: [Select]
void CTCPClient::ListenLoop()
{
sf::SocketTCP * socket = (sf::SocketTCP*)(m_socket);
if(socket)
{
char buffer[TCP_MAX_SIZE] = "";
size_t recievedSize = 0;

while(m_online)
{
if(socket->Receive(buffer, TCP_MAX_SIZE, recievedSize) == sf::Socket::Done)
{
if(HandleInternalMessage(buffer, recievedSize) == false ||
(m_forwardInternalMessage == true))
{
(*TCPClientServerResponse)(buffer, recievedSize);
}
}
else
{
PrintLog(TCP_EVENT, "Closing down connection with server");
m_online = false;
}
}
}
socket->Close();
}

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
SFML Network buffer question
« Reply #3 on: January 22, 2010, 09:38:08 am »
Can you show the implementation of your GetClientId function?
Laurent Gomila - SFML developer

fredrick

  • Newbie
  • *
  • Posts: 20
    • View Profile
SFML Network buffer question
« Reply #4 on: January 22, 2010, 09:50:38 am »
Code: [Select]
typedef struct ClientInfo_t
{
size_t id; // Client reference id (0 is valid)
bool   clientAuthenticated; // Client sends connect message to be authenticated
/*sf::IPAddress*/ void * clientAddress;
/*sf::SocketTCP*/ void * clientSocket;
}ClientInfo_t;


Code: [Select]
size_t CTCPServer::GetClientId(void *socketHandle)
{
size_t clientId = 0;
bool clientFound = false;

sf::SocketTCP * socket = (sf::SocketTCP*)(socketHandle);

for(std::vector<ClientInfo_t*>::iterator it = m_clients.begin(); it != m_clients.end(); it++)
{
sf::SocketTCP  clientSocket = *(sf::SocketTCP *)(*it)->clientSocket;
if(clientSocket == *socket)
{
clientFound = true;
break;
}
clientId++;
}

if(!clientFound)
{
PrintLog(TCP_ERROR, "%s Unable to find client", AT);
clientId = -1;
}
return clientId;
}

fredrick

  • Newbie
  • *
  • Posts: 20
    • View Profile
SFML Network buffer question
« Reply #5 on: January 22, 2010, 01:13:58 pm »
I don't think i have a problem with sending to wrong socket,
temporary solution was to add sleep for 5 ms in the sfml send function
and that solved my problems. But its not a optimal fix in my opinion.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
SFML Network buffer question
« Reply #6 on: January 22, 2010, 01:46:54 pm »
So, where exactly do you send multiple packets to the server? Is it happening in the TCPClientServerResponse callback?
Laurent Gomila - SFML developer

fredrick

  • Newbie
  • *
  • Posts: 20
    • View Profile
SFML Network buffer question
« Reply #7 on: January 22, 2010, 02:04:51 pm »
This is the sequence of events when the problem occurs:

1: Server goes online, listens to incoming connections.

2: Client connects, sends a connection message to the server.

3: While server process the initial message because it queries sqlite  
database for user info etc and gets some delay the client sends another packet because on the client side these calls are in the same stack.

4: Server completes the initial packet and sends back to client that it was allowed to connect or not - then get that second message from the selector whenever its ready.

5: Server is processing the second packet, at this time the client is idle
and the server respond with a packet and this is the one that randomly without the sleep code never reach the client.


So in summary: I can send packets to the server like crazy, they are always delivered while clients if the response is to quick looses their packet.


The difference between the client code from server is no selector.

Client runs on a GUI so it has a dedicated thread, while the server runs on the main thread.


I can do some isolated tests and remove all the noise(other code\stuff) and see what i come up with. Also happy to send you my library.

Thanks for your quick response so far!

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
SFML Network buffer question
« Reply #8 on: January 22, 2010, 02:19:22 pm »
Have you tried using sf::Packet instead of raw data? With raw data there may not be a 1:1 mapping between send and receive calls (ie. you can receive packet#1 + beginning of packet#2 in a single receive call, or only a part of packet#1).
Laurent Gomila - SFML developer

fredrick

  • Newbie
  • *
  • Posts: 20
    • View Profile
SFML Network buffer question
« Reply #9 on: January 22, 2010, 02:24:08 pm »
is there any extra overhead \ packet size cost of using sfml packet structure. ?

I went for raw data so i was able to construct a 3 byte packet header for packet types + size ( unsigned char packetType , unsigned short packetSize).

I guess i should use UDP if i am that concerned about header size but that was the route i took while planing the framework.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
SFML Network buffer question
« Reply #10 on: January 22, 2010, 02:30:09 pm »
sf::Packet only adds a 32-bits integer size. I think it's worth it for the tiny extra cost of 2 bytes.
Laurent Gomila - SFML developer

 

anything