1
Network / 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:
*.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:
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?
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;
}
#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
#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?