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

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Merakon

Pages: [1]
1
Network / sf::SocketTCP.Send() & sf::SocketTCP.Receive() Threadsaf
« on: March 19, 2010, 04:51:14 pm »
Quote from: "Mindiell"
The question is not why using Send and Receive on the same Socket : Everybody (As far as I know) use this.
The real question is why could you want to Receive and Send at the same time ?

The original poster and I don't necessarily want to Receive and Send at the same time, and the original poster pointed out that when he tried to protect them with a mutex he ran into a deadlock. This is because the Receive function was a blocking call, so if you lock a mutex before the blocking call and then the server never sends anything (let's say it's waiting for clients to send it information before it relays information down), you'll hit a deadlock on the mutex.

As with my previous post, I believe the best way to approach this is by using a non-blocking socket. However, I'm not a network coding expert and I don't know if a non-blocking socket is going to cause other problems that I'm not aware of at present.

2
Network / sf::SocketTCP.Send() & sf::SocketTCP.Receive() Threadsaf
« on: March 19, 2010, 04:18:26 pm »
The reason that I want to Send and Receive on the same socket is simplicity of code. If I can't Send and Receive on the same socket, that means each client needs to create two sockets to connect to the server and the server needs two sockets per client.

Anyway, I seem to have come to a simple solution by using SetBlocking(false) on the socket. This prevents the Receive call from causing a deadlock, and allows me to use a Mutex to protect the sf::Socket object. I hope this doesn't cause other problems, but for now it works. Here is the code, for anyone's benefit and/or feedback:

Code: [Select]

// netclient.h

// Note: I also include a project .h which uses namespace std
#include <SFML/Network.hpp>
#include <SFML/System.hpp>

class NetClient
{
public:
NetClient();
virtual ~NetClient();

bool ConnectToServer();

bool SendMessage(string message);

sf::SocketTCP   m_Socket;
sf::Mutex       m_SocketMutex;

protected:
sf::Thread    * m_pThread;
};



Code: [Select]

// netclient.cpp

#include "netclient.h"
#include <iostream>

NetClient::NetClient() : m_pThread(NULL)
{
}

NetClient::~NetClient()
{
if (this->m_Socket.IsValid())
{
this->m_SocketMutex.Lock();
this->m_Socket.Close();
this->m_SocketMutex.Unlock();
}
if (this->m_pThread != NULL)
{
this->m_pThread->Wait();
delete this->m_pThread;
}
}

void Receiver(void* UserData)
{
NetClient * netClient = static_cast<NetClient*>(UserData);

bool keepGoing = true;
while (keepGoing)
{
sf::Socket::Status status;
sf::Packet packet;
netClient->m_SocketMutex.Lock();
status = netClient->m_Socket.Receive(packet);
netClient->m_SocketMutex.Unlock();

if (status == sf::Socket::Disconnected)
{
keepGoing = false;
}
else if (status == sf::Socket::Error)
{
cout << "Encountered an error reading from socket.\n" << endl;
keepGoing = false;
}
else if (status == sf::Socket::Done)
{
string message;
packet >> message;
cout << "Server says : \"" << message << "\"" << endl;
}
}
}

bool NetClient::ConnectToServer()
{
const int Port = 2839;

// Ask for server address
sf::IPAddress ServerAddress;
do
{
cout << "Type the address or name of the server to connect to : ";
cin  >> ServerAddress;
}
while (!ServerAddress.IsValid());
cin.ignore(10000, '\n');

// Connect to the server
if (this->m_Socket.Connect(Port, ServerAddress) != sf::Socket::Done)
return false;

this->m_Socket.SetBlocking(false);

this->m_pThread = new sf::Thread(&Receiver, this);
thus->m_pThread->Launch();

return true;
}

bool NetClient::SendMessage(string message)
{
if (this->m_Socket.IsValid() == false)
{
cout << "Error: Can't send network message. Socket is invalid." << endl;
return false;
}

sf::Packet packet;
packet << message;
this->m_SocketMutex.Lock();
this->m_Socket.Send(packet);
this->m_SocketMutex.Unlock();
return true;
}

3
Network / sf::SocketTCP.Send() & sf::SocketTCP.Receive() Threadsaf
« on: March 19, 2010, 01:07:56 am »
I had the same question today.

Has anyone determined whether SFML's SocketTCP class is thread-safe, at least with regard to Send and Receive?

If not, has anyone made any code modifications that they could share?

P.S. Laurent: I like SFML a lot!

Pages: [1]