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

Author Topic: Thread + TCP + vector = fail.  (Read 1988 times)

0 Members and 1 Guest are viewing this topic.

untorched

  • Newbie
  • *
  • Posts: 3
    • View Profile
Thread + TCP + vector = fail.
« on: December 27, 2013, 04:06:02 am »
Hello again!
I'm writting simple TCP server(like chat or sth) with assign ID to every client.
Ok, I'll show.

*.cpp:
#include "stdafx.h"
#include "cServer.h"

void cServer::init()
{
    cServer::instance().startServer();
    cServer::instance().serverProcess();
}

void cServer::startServer() {
    if(this->m_ServerSock.listen(GS_PORT) == sf::Socket::Status::Done) {
        cLogger::Log("Server started at port %d", GS_PORT);
    }
    else {
        return;
    }

    this->m_ServerSock.setBlocking(false);
    this->m_Selector.add(this->m_ServerSock);
}

void cServer::serverProcess() {
    int iIndex = 0;
    char buffer[7048];
    std::size_t buffer_size;

    while(1) {
        if(this->m_Selector.wait()) {
            if(this->m_Selector.isReady(this->m_ServerSock)) {
                int i = this->getFreeIndex();
                if(i == -1) {
                    this->m_Clients.push_back(std::move(Client()));
                    if(this->m_ServerSock.accept(*this->m_Clients.back().socket) == sf::Socket::Status::Done) {
                        this->m_Selector.add(*this->m_Clients.back().socket);
                        this->m_Clients.back().connected = true;
                        cLogger::Log("[DEBUG] Client[id: %d] connected", this->m_Clients.size()-1);
                    }
                    else {
                        this->m_Clients.pop_back();
                    }
                }
                else {
                    this->m_Clients[i] = std::move(Client());
                    if(this->m_ServerSock.accept(*this->m_Clients[i].socket) == sf::Socket::Status::Done) {
                        this->m_Selector.add(*this->m_Clients.back().socket);
                        this->m_Clients[i].connected = true;
                        cLogger::Log("[DEBUG] Client[id: %d] connected", i);
                    }
                }
            }
            else {
                iIndex = 0;
                for(auto it = this->m_Clients.begin(); ((it != this->m_Clients.end())); it++) {
                    if(this->m_Selector.isReady(*(*it).socket)) {
                        switch ((*(*it).socket).receive(buffer, sizeof(buffer), buffer_size)) {
                            case sf::Socket::NotReady:
                                break;

                            case sf::Socket::Disconnected:
                                this->m_Selector.remove(*(*it).socket); //stop listening to the client that disconnected
                                (*it).connected = false;
                                cLogger::Log("[DEBUG] Client[id: %d] disconnected", iIndex);
                                break;

                            case sf::Socket::Error:
                                this->m_Selector.remove(*(*it).socket); //stop listening to the client that disconnected
                                (*it).connected = false;
                                cLogger::Log("[DEBUG] Client[id: %d] disconnected", iIndex);
                                break;

                            case sf::Socket::Done:
                                cLogger::Log("[DEBUG] Client[id: %d] said: %s", iIndex, buffer);
                                break;
                        }
                    }
                    iIndex++;
                }
            }
        }
    }
}

int cServer::getFreeIndex() {
    int iIndex = 0;

    for(auto it = this->m_Clients.begin(); ((it != this->m_Clients.end())); it++) {
            if((*it).connected == false) {
                return iIndex;
            }
            iIndex++;
    }
    return -1;
}
 

*.h:
#ifndef CSERVER_H
#define CSERVER_H

class Client
{
    public:
        // Default constructor
        Client()
        : socket(new sf::TcpSocket)
        {
        }

        // Move constructor
        Client(Client&& source)
        : socket(std::move(source.socket))
        {
        }

        // Move assignment operator
        Client& operator= (Client&& source)
        {
            socket = std::move(source.socket);
            return *this;
        }

        std::unique_ptr<sf::TcpSocket> socket;
        bool connected;
};

class cServer
{
    // Singleton
    public:
        static cServer& instance() {
            static cServer instance;
            return instance;
        }
    private:
        cServer(const cServer&);
        cServer& operator=(const cServer&);
    // Singleton end

    private:
        sf::SocketSelector m_Selector;
        sf::TcpListener m_ServerSock;
        std::vector<Client> m_Clients;

        cServer() {}
        void startServer();
        void serverProcess();
        int getFreeIndex();

    public:
        static void init();
};

#endif // CSERVER_H
 

Now, when function getFreeIndex() is called is looking for varible "connected" in pushed classes to vector, but all varibles are false, only last one have true. This is very sad and I don't know why.

Next problem is when I want close socket eg. when server receive message but this not closing socket. I'm doing like this:
this->m_Clients[client_index].socket->disconnect();
Should be working, but it's not.

Please help me ;c

//Edit:
When i change -std=c++11 to -std=c++0x, my varible in getFreeIndex() is randomized but it's > 0(false) and last one is 1(true). Wtf?
« Last Edit: December 27, 2013, 04:26:15 am by untorched »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Thread + TCP + vector = fail.
« Reply #1 on: December 27, 2013, 08:11:42 am »
I didn't look at your entire source code, but the constructors of your Client class never initialize the "connected" member. That probably explains the weird results of your function.
Laurent Gomila - SFML developer