Hey that's an even better idea, just pass in the accepted socket instead of an entire blank client that only has a socket. I'll have to add a client function that moves a socket into the client.socket though.
Edit: Now that I'm at my computer, here's how it does it:
class Client
{
public:
//Default constructor-- should probably never be used...
Client()
: socket(new sf::TcpSocket)
{
ID = -1;
}
//Move constructor
Client(Client&& source)
: socket(std::move(source.socket))
{
ID = source.ID;
name = source.name; //client's user name
}
//Move assignment operator
Client& operator= (Client&& source)
{
ID = -1;
socket = std::move(source.socket);
return *this;
}
int loadClient(const std::string &clientName); //looks up a user based on their name
public:
std::unique_ptr<sf::TcpSocket> socket; //socket handling communication to this client
std::string name; //client's user name
int ID; //client's unique ID
};
class Server
{
public:
Server(): mWindow(sf::VideoMode(400, 400), "Server Connection", sf::Style::Close){};//force window to certain size
void run();
sf::RenderWindow mWindow;
public:
private:
void processEvents(); //handles input
void loginAttempt(std::unique_ptr<sf::TcpSocket> &inputSocket); //handles login attempts
private:
std::list<Client> clientList; //sockets we will use to communicate
sf::SocketSelector selector; //used to handle multiple clients
sf::TcpListener listener; //will listen on a specific port for an incoming connection
};
void Server::run()
{
if (listener.listen(port) != sf::Socket::Done) {
std::cout << "Failed to listen to port " + std::to_string(port) + ". Something else already attached to port?\n";
return;}
std::cout << "Currently listening to port " + std::to_string(port) + ". Waiting for first connection...\n";
selector.add(listener); //put the new connection listener into our selector
listener.setBlocking(false); //we no longer want to block when checking for new connections
while(mWindow.isOpen()) //main server hosting loop
{
if (selector.wait(sf::seconds(1.f))) //server sits and waits for an event to occur on the selector
{
if(selector.isReady(listener)) //we have a new incoming connection
{
std::unique_ptr<sf::TcpSocket> tempSocket(new sf::TcpSocket);
if (listener.accept(*tempSocket) == sf::Socket::Done)
std::thread (&Server::loginAttempt, this, std::move(tempSocket)).detach();//create a new thread to handle the login events
}
...
void Server::loginAttempt(std::unique_ptr<sf::TcpSocket> &inputSocket)
{
Client *client = new Client();
client->socket = std::move(inputSocket);
bool success = false; //indicates login success or failure
...
if (!success) //client failed to pass all conditions to connect to the server, so we remove them
{
selector.remove(*(client->socket)); //stop listening to the client that disconnected
std::cout << "Client failed to login.\n";
return;
}
else
{
//client passed all conditions to connect to server
clientList.push_back(std::move(*client)); //push the client we made into the list!
return;
}
}