Handling multiple client sockets with SFML - c++

I am currently trying to write the networking part of a little multiplayer game, and I am facing a problem to store my TCP sockets which are, in SFML, non-copyable (I am a beginner in C++).
I have three classes : Server, Client (a server-side class used to store all informations about a connecting client) and ClientManager, which is in charge of storing all clients and giving them IDs, etc.
ClientManager.h
class ClientManager {
public:
ClientManager();
std::map<int, Net::Client*> getClients();
int attribID();
void addClient(Net::Client *client);
sf::TcpSocket getClientSocket(int id) throw(std::string);
void setClientSocket(int id, sf::TcpSocket);
private:
std::map<int, Net::Client*> m_clients;
std::map<int, sf::TcpSocket> m_clientSockets;
std::vector<int> m_ids;
int m_lastID;
};
What I planned to do originally, when a client connects, is :
void Net::Server::waitForClient() {
while(true) {
if(m_listener.accept(m_tcpSocket) != Socket::Done) {
cout << "Error happened during client connection. skipping. " << endl;
return;
}
int newID = m_clientManager.attribID();
this->m_clientManager.addClient(new Net::Client(newID, m_tcpSocket, m_tcpSocket.getRemoteAddress()));
}
}
So, adding a new Client into ClientManager's list, with its ID, a TcpSocket to send info and his address.
But, the problem is that SFML's TcpSocket class is not copyable, which means I can't copy it to a Client like this.
I could pass it as a pointer to the original TcpSocket, but what if another client connects ? The data the pointer points to will have change and the program will bug. I do not know if this behavior will be the same with smart pointers, but I think so (but I don't master them at all).
Storing them in a std::map or std::vector causes the same problem, as they both copy the object. Storing them as pointers (in the map) to the original TcpSocket will cause the same problem as before, because the socket will change too, and the pointers will point to the same object.
How can I store my sockets without having to use references, pointers or to copy my object ?
Any help will be greatly appreciated :)

It's going to be a real pain to do without pointers. Personally I use smart pointers to manage the sockets themselves (std::vector<std::unique_ptr<sf::TcpSocket>> or similiar), along with `sf::SocketSelector' to manage the actual communication

Related

simple thread safe vector for connections in grpc service

I'm trying to learn about concurrency, and I'm implementing a small connection pool in a grpc service that needs to make many connections to a postgres database.
I'm trying to implement a basic connectionPool to prevent creating a new connection for each request. To start, I attempted to create a thread safe std::vector. When I run the grpc server, a single transaction is made, and then the server blocks, but I can't reason out what's going on. Any help would be appreciated
class SafeVector {
std::vector<pqxx::connection*> pool_;
int size_;
int max_size_;
std::mutex m_;
std::condition_variable cv_;
public:
SafeVector(int size, int max_size) : size_(size), max_size_(max_size) {
assert(size_ <= max_size_);
for (size_t i = 0; i < size; ++i) {
pool_.push_back(new pqxx::connection("some conn string"));
}
}
SafeVector(SafeVector const&)=delete; // to be implemented
SafeVector& operator=(SafeVector const&)=delete; // no assignment keeps things simple
std::shared_ptr<pqxx::connection> borrow() {
std::unique_lock<std::mutex> l(m_);
cv_.wait(l, [this]{ return !pool_.empty(); });
std::shared_ptr<pqxx::connection> res(pool_.back());
pool_.pop_back();
return res;
}
void surrender(std::shared_ptr<pqxx::connection> connection) {
std::lock_guard<std::mutex> l(m_);
pool_.push_back(connection.get());
cv_.notify_all();
}
};
In main, I then pass a SafeVector* s = new SafeVector(4, 10); into my service ServiceA(s)
Inside ServiceA, I use the connection as follows:
std::shared_ptr<pqxx::connection> c = safeVector_->borrow();
c->perform(SomeTransactorImpl);
safeVector_->surrender(c);
I put a bunch of logging statements everywhere, and I'm pretty sure I have a fundamental misunderstanding of the core concept of either (1) shared_ptr or (2) the various locking structures.
In particular, it seems that after 4 connections are used (the maximum number of hardware threads on my machine), a seg fault (error 11) happens when attempting to return a connection in the borrow() method.
Any help would be appreciated. Thanks.
smart pointers in C++ are about object ownership.
Object ownership is about who gets to delete the object and when.
A shared pointer means that who gets to delete and when is a shared concern. Once you have said "no one bit of code is permitted to delete this object", you cannot take it back.
In your code, you try to take an object with shared ownership and claim it for your SafeVector in surrender. This is not permitted. You try it anyhow with a call to .get(), but the right to delete that object remains owned by shared pointers.
They proceed to delete it (maybe right away, maybe tomorrow) and your container has a dangling pointer to a deleted object.
Change your shared ptrs to unique ptrs. Add move as required to make it compile.
In surrender, assert the supplied unique ptr is non-empty.
And whike you are in there,
cv_.notify_one();
I would also
std::vector<std::unique_ptr<pqxx::connection>> pool_;
and change:
pool_.push_back(std::move(connection));
if you don't update the type of pool_, instead change .get() to .release(). Unlike shared ptr, unique ptr can give up ownership.

C++ objects and threads

I am doing a simple server apllication, where you can have multiple connections, each connection is a single thread. This is the example I would like it to look like(it doesn't work), there is a collection of threads where each thread instantiates an object of the class connection:
class connection{};
class server{
std::vector<std::thread> active_connections;
public:
void listen() {active_connections.push_back(std::thread(connection));}
};
I have been searching for the solution, but the best I could find were some member function threads. The solution turned quite wrong when I tested it, for example:
class connection{};
class server{
std::vector<std::thread> active_connections;
public:
void new_connection() { ... }
void listen() {
active_connections.push_back(std::thread(&server::new_connection,this)); }
};
The message was: error: use of deleted function ‘std::thread::thread(const std::thread&).
Does that mean the std::thread class wants to copy the server class?? I don't know C++ that much so please don't flame, I'm only asking.
Thanks!
EDIT:
This is where this happens:
void server::do_listen()
{
int addr_size = sizeof(sockaddr_in);
sockaddr_in client_sock;
connection_info cn_info;
while(true)
{
int csock;
if((csock = accept(server_sock, (sockaddr*)&client_sock, (socklen_t*)&addr_size)) != -1)
{
printf("Incomming connection from %s.\n", inet_ntoa(client_sock.sin_addr));
memset(&cn_info,0, sizeof(connection_info));
cn_info.sock_addr = client_sock;
cn_info.sock = csock;
std::thread thr(&server::new_connection, *this, cn_info);
thr.join();
}
}
}
This is by far. The server::new_connection() is still empty.
The problem is here:
std::thread thr(&server::new_connection, *this, cn_info);
^
You're binding a copy of the server object; which isn't copyable because it contains (a container of) non-copyable thread objects. Instead, bind a pointer:
std::thread thr(&server::new_connection, this, cn_info);
Some might find a lambda more readable; this captures the this pointer and cn_info by value:
std::thread thr([=]{new_connection(cn_info);});
As a commentor mentions, you could obfuscate the solution by binding a reference wrapper:
std::thread thr(&server::new_connection, std::ref(*this), cn_info);
but I prefer to remove, rather than add, complexity where possible.
Does that mean the std::thread class wants to copy the server class?
No, that means a copy of a std::thread is made somewhere, but that's forbidden as std::thread in NonCopyable (note the thread(const thread&) = delete; in the list of constructors).
You should eliminate any code that performs a copy of a thread. The one you've posted doesn't perform such copy.
An example where a copy is made "behind the scene" would be a push_back in a vector of a thread variable, i.e.:
std::thread myThread;
myVector.push_back(myThread);
In your code:
active_connections.push_back(std::thread(&server::new_connection,this));
as you're pushing back a temporary, it doesn't get copied but moved into the vector.
More a design question to you author:
You create one thread for one connection. If you have ten connections you have ten threads. But what do you do if you have 10000 connections you want to handle? I'm not sure your operating system likes that.
A much better connection handling approach - only in my opinion - would be if you only have N threads that handle your network connections. If your computer has e.g. six cores you could spend one, two or more threads only for the network stuff. So you have a thread pool of a certain size for this.
The proactor pattern could be interesting for you:
http://en.wikipedia.org/wiki/Proactor_pattern
If you're looking for a library that could handle such things, you could look to the upcoming C++ Boost library named Boost.Asynchronous:
https://github.com/henry-ch/asynchronous
This library is still in development, but really good. I've made some simple client/server applications with the library.

C++ How can I send an object via socket?

I have a question for you.
I have this class:
`
#define DIMBLOCK 128
#ifndef _BLOCCO_
#define _BLOCCO_
class blocco
{
public:
int ID;
char* data;
blocco(int id);
};
#endif
blocco::blocco(int id)
{
ID = id;
data = new char[DIMBLOCK];
}
`
and the application has a client and a server.
In the main of my server I instantiate an object of this class in this way:
blocco a(1);
After that I open a connection between the client and the server using sockets.
The question is: how can I send this object from the server to the client or viceversa?
Could you help me please?
It's impossible to send objects across a TCP connection in the literal sense. Sockets only know how to transmit and receive a stream of bytes. So what you can do is send a series of bytes across the TCP connection, formatted in such a way that the receiving program knows how to interpret them and create an object that is identical to the one the sending program wanted to send.
That process is called serialization (and deserialization on the receiving side). Serialization isn't built in to the C++ language itself, so you'll need some code to do it. It can be done by hand, or using XML, or via Google's Protocol Buffers, or by converting the object to human-readable-text and sending the text, or any of a number of other ways.
Have a look here for more info.
you can do this using serialization. This means pulling object into pieces so you can send these elements over the socket. Then you need to reconstruct your class in the other end of connection. in Qt there is QDataStream class available providing such functionality. In combination with a QByteArray you can create a data package which you can send. Idea is simple:
Sender:
QByteArray buffer;
QDataStream out(&buffer);
out << someData << someMoreData;
Receiver:
QByteArray buffer;
QDataStream in(&buffer);
in >> someData >> someMoreData;
Now you might want to provide additional constructor:
class blocco
{
public:
blocco(QDataStream& in){
// construct from QDataStream
}
//or
blocco(int id, char* data){
//from data
}
int ID;
char* data;
blocco(int id);
};
extended example
I don't know how much flak I'll get for this, but well I tried this and though I should share it. I am a beginner at socket programming so don't get pissed off.
What I did is I created an array of characters which is of the size of the class (representing the block of memory at the server side). Then I recved the block of memory at the client side and typecast that block of memory as an object and voila!! I managed to send an object from client to server.
Sample code:
blocco *data;
char blockOfData[sizeof(*data)];
if(recv(serverSocket, blockOfData, sizeof(*data), 0) == -1) {
cerr << "Error while receiving!!" << endl;
return 1;
}
data = (blocco *)blockOfData;
Now you can do whatever you want with this data using this as a pointer to the object. Just remember do not try to delete/free this pointer as this memory is assigned to the array blockOfData which is on the stack.
Hope this helps if you wanted to implement something like this.
PS: If you think what I've done is poor way of coding please let me know why. I don't know why this is such a bad idea(if it is in fact a bad idea to do this). Thanks!!

winsock, message oriented networking, and type-casting the buffer from recv

Okay, I actually don't have code as of yet because i'm just picking out a framework for the time being, but i'm still a little baffled about how i wish to go about this :.
Server side, i wish to have a class where each instance has a socket and various information identifying each connection. each object will have it's own thread for receiving data. I understand how i'll be implementing most of that, but my confusion starts just as i get to the actual transfer of data between server and client. I'll want to have a bunch of different message structs for specific cases, (for example CONNECT_MSG , DISCONNECT_MSG, POSTTEXT_MSG, etc) and then all i have to do is have a char * point at that struct and then pass it via the send() function.
But as i think on it, it gets a little complicated at that point. Any of those different message types could be sent, and on the receiving end, you will have no idea what you should cast the incoming buffer as. What i was hoping to do is, in the thread of each connection object, have it block until it receives a packet with a message, then dump it into a single queue object managed by the server(mutexes will prevent greediness) and then the server will process each message in FIFO order independent of the connection objects.
I havn't written anything yet, but let me write a little something to illustrate my setup.
#define CONNECT 1000
struct GENERIC_MESSAGE
{
int id;
}
struct CONNECT_MESSAGE : public GENERIC_MESSAGE
{
m_username;
}
void Connection::Thread()
{
while(1)
{
char buffer[MAX_BUFFER_SIZE]; // some constant(probably 2048)
recv(m_socket, buffer, MAX_BUFFER_SIZE, 0);
MESSAGE_GENERIC * msg = reinterpret_cast<MESSAGE_GENERIC *> (buffer);
server->queueMessage(msg);
}
}
void Server::QueueMessage(MESSAGE_GENERIC * msg)
{
messageQueue.push(msg);
}
void Server::Thread()
{
while(1)
{
if(!messageQueue.empty())
ProcessMessages();
else
Sleep(1);
}
}
void Server::ProcessMessages()
{
for(int i = 0; i < messageQueue.size(); i++)
{
switch(messageQueue.front()->id)
{
case CONNECT:
{
// the part i REALLY don't like
CONNECT_MESSAGE * msg = static_cast<CONNECT_MESSAGE *>(messageQueue.front() );
// do the rest of the processing on connect
break;
}
// other cases for the other message types
}
messageQueue.pop();
}
}
Now if you've been following up until now, you realize just how STUPID and fragile this is. it casts to the base class, passes that pointer to a queue, and then just assumes that the pointer is still valid from the other thread, and even then whether or not the remaining buffer after the pointer for the rest of the derived class will always be valid afterward for casting, but i have yet to find a correct way of doing this. I am wide open for ANY suggestions, either making this work, or an entirely different messaging design.
Before you write even a line of code, design the protocol that will be used on the wired. Decide what a message will consist of at the byte level. Decide who sends first, whether messages are acknowledged, how receivers identify message boundaries, and so on. Decide how the connection will be kept active (if it will be), which side will close first, and so on. Then write the code around the specification.
Do not tightly associate how you store things in memory with how you send things on the wire. These are two very different things with two very different sets of requirements.
Of course, feel free to adjust the protocol specification as you write the code.

Streaming over a TCP/IP connection

I find myself constantly running into a situation where I have a set of messages that I need to send over a TCP/IP connection. I have never found a good solution for the design of the message class. I would like to have a message base class where all messages derive from it. Since each message will have different fields, this would allow me to access the fields through member variables or methods. Something like...
class message_base
{
public:
message_base();
virtual ~message_base();
unsigned int type;
};
class message_control : public message_base
{
public:
message_control();
virtual ~message_control();
unsigned int action;
};
This way I can create a message_control and access the action member for assigning to and reading from. I can also pass the messages around without writing too much code.
The problem arises when I need to send the messages. If I override the operator<< and operator>> then I can send the messages over one variable at a time. The problem with that solution is that with so many calls to send data, the context switches will slam the processor. Also, the streaming operator ends up the the socket class and not in the message class where I would prefer it lived.
socket& socket::operator<<(message_control& message)
{
sock << type;
sock << action;
}
If I pack the data in a buffer, I get away from C++ and more into the realm of C and find myself making generous use of pointers and the like. And, modifying the code is difficult and error prone. And, the streaming operator is still in the socket class and not the message class.
socket& socket::operator<<(message_control& message)
{
byte* buffer = new byte[sizeof(message.type) + sizeof(message.action)];
memcpy(buffer, message.type, sizeof(message.type));
memcpy(buffer + sizeof(message.type), message.action, sizeof(message.action));
sock.send(buffer);
}
My last attempt used an intermediate class to handle packing and unpacking the members in a buffer. The messages could implement operator<< and operator>> to the buffer class and then the buffer class is sent to the socket. This works but doesn't feel right.
class socket
{
public:
socket();
~socket();
socket& operator<<(buffer& buff);
};
class buffer
{
public:
buffer() {m_buffer = new byte[initial_size];}
~buffer() {delete [] m_buffer;}
buffer& operator<<(unsigned int value);
private:
byte* m_buffer;
};
void message_control::serialize(buffer& buff)
{
buff << type;
buff << action;
}
I can't help but feel there is an elegant solution to this problem. I can't find any design patterns that match what I am trying to accomplish. Has anyone experienced this problem and come up with a going design that doesn't make you feel like you would be better off with good old pointers and an array of bytes?
Update
I failed to mention in my original post that I am most often dealing with very well define wire protocols. That is why I typically need to roll my own solution and can't use any of the wonderful toolkits available for messaging over a network connection.
"The problem with that solution is that with so many calls to send data, the context switches will slam the processor. Also, the streaming operator ends up the the socket class and not in the message class where I would prefer it lived."
The solution to the second problem is to define operator<< as a non-member function in the namespace which contains the message class, instead of as a member function of the socket class. ADL will find it.
The solution to the first problem is to buffer the data within your process, and then flush at the end of each message. If Nagle buffering isn't preventing context switches, then you might be able to achieve this by messing with the socket, I don't know. What you certainly can do, though, is prepare each message before sending in a more C++-ish way. Replace:
sock << type;
sock << action;
with:
stringstream ss;
ss << type;
ss << action;
sock << ss.str();