Server with multiple clients and message forwarding - c++

I have a Server running and listening on a port for incomming connections. When a Client establishes a connection it is put in a ThreadPool and set on run.
The Clients should be able to send messages between them, not only to the server, which basically forwards the received messages to another client.
I am using C++ and Qt, so when I get a new Client I put it in a QThreadPool:
Client c = new Client();
pool->start(c);
But I cannot search for specific Clients in this pool therefore I thought of storing the Clients in an List as well which can be searched.
The clients have a data structure with outgoing and incoming messages which can then be handled by iterating through the list with the clients by a server thread.
Is this a good approach or is there a better way to solve this? Is the pool even necessary any more if I store them in the List too?

Related

Multiple writes on same socket c++

I'm currently trying to develop a server and some clients which communicate with each other using something like a proxy in the middle. The "proxy" will have sockets opened to every client and server on the system. This means that I'm currently using threads to keep all the connections opened. Every time a client decides to send a message it uses its socket with the proxy and sends the message. Then the proxy will propagate the message to every other node using the respective socket.
As you can see, a node can be receiving messages by having the proxy writing on the socket or a node may want to send messages by writing on the socket.
How do I guarantee that the content in the socket does not get overwritten ? Do I have to use mutexes to lock the access to the socket ? What is a good practice to solve this problem ?
Connections are bi-directional. Content going one way does not overwrite content going the other way. No mutex is needed for this.
Besides, you couldn't use a mutex anyway, as both sides of the connection are separate.

Boost::Beast Websocket Bidirection Stream (C++)

I'm looking into using the Boost::Beast websocket library to create an asynchronous bidirectional pipe to pass data between a server and a client. I leveraged some code from the async example (I can post some at a later time if necessary, don't have access to it now). I currently have a class which creates several threads running a SocketListener. When a client connects, it creates a Session shared_ptr to do the async read and write functions. The problem is, this session object will only write out when the client has sent me a message. I'm looking for an implementation that allows my server to write on demand to all the clients connected to it and also listen for incoming data from those connections.
Is this possible? Am I using the wrong technique for this? The other way I though this may be achievable is to have an incoming websocket and and outgoing websocket. Incoming would allow a client to drop configurations for the server and outgoing would just monitor a message queue and do a async write if a message is available.
Thanks!
Is this possible?
Yes
Am I using the wrong technique for this?
No
The other way I though this may be achievable is to have an incoming websocket and and outgoing websocket, and No respectively.
That is not necessary, a websocket stream is full-duplex. You can read and write at the same time.
outgoing would just monitor a message queue and do a async write if a message is available.
This is the correct approach, but you can do that in the same Session object that also handles the reads.
Here's an example that reads continuously and can also write full-duplex: https://github.com/vinniefalco/CppCon2018

c++ socket accept, list of connected clients

I have a few question about socket in c++!
First question, let's say that he writes a server for the game in which he will play 200 people at once, but accept is blocked because he already serves one client, how to deal with it?
Second question, how to download a list of all currently connected clients, so that you can then send a message to everyone?
I have a few question about socket in c++!
For future reference, please post only one question at a time. If you have multiple questions, post them separately.
let's say that he writes a server for the game in which he will play 200 people at once, but accept is blocked because he already serves one client, how to deal with it?
Use sockets in non-blocking mode, using select()/(e)poll() or other callback mechanisms to know which sockets have pending activity and when.
Otherwise, use accept() in a separate thread than other thread(s) used to service connected clients.
how to download a list of all currently connected clients, so that you can then send a message to everyone?
The server is responsible for keeping track of its connected clients. Then it can loop through that list when needed.
If a client wants to send a message to every other client, the best option is for it to send a single message to the server and ask the server to relay the message to every other client.
Otherwise, the client would have to request the list from the server, and then send a message to every other client individually.

TCP push-pull socket server design

I am designing a cross-platform messaging service as a learning exercise. I have programmed socket-based servers before, but always a "client-polls-server" design, like a web server. I want to be able to target mobile platforms, and I read that polling is a battery drain, so I would like to do push notification.
The server will be TCP-based, written in C++. What I'm having trouble getting my head around is how to manage the bi-directional nature of the design. I need a client to be able to send packets to the server as normal, but also listen for packets. How do I mitigate situations like, the client is sending data when the server is trying to send to it, or it's blocked listening for data but then needs to send something?
For example, consider the following crude diagram:
So, let's say client A is in the middle of sending a chunk of data (arrow 1). While this is happening, client B sends a message (arrow 2), which causes the server to attempt to send data back to client A (arrow 3), but client A hasn't finished sending arrow 1 yet. What happens in this instance? Should I setup 2 separate ports on each client, one for inbound, one for outbound? Do I need to keep track of the state of each connection?
Or is there a better approach to this altogether?
One socket port is inherently bidirectional. To handle both inbound and outbound traffic more or less concurrently you need to use nonblocking sockets.
I think the solution is pretty simple. The TCP server should have a list with connected clients. Since a TCP connection is bi-directional, the push mechanism is quite simple.
Another important thing, as long as your server isn't multithreaded, you can read from or write to one client at the same time.

Multithreaded Server Issue

I am writing a server in linux that is supposed to serve an API.
Initially, I wanted to make it Multi-threaded on a single port, meaning that I'd have multiple threads working on various request received on a single port.
One of my friends told me that it not the way it is supposed to work. He told me that when a request is received, I first have to follow a Handshake procedure, create a thread that is listening to some other port dedicated to the request and then redirect the requested client to the new port.
Theoretically, it's very interesting but I could not find any information on how to implement the handshake and do the redirection. Can someone help?
If I'm not wrong in interpreting your responses, once I create a multithreaded server with a main thread listening to a port, and creates a new thread to handle requests, I'm essentially making it multithreaded on a single port?
Consider the scenario where I get a large number of requests every second. Isn't it true that every request on the port should now wait for the "current" request to complete? If not, how would the communication still be done: Say a browser sends a request, so the thread handling this has to first listen to the port, block it, process it, respond and then unblock it.
By this, eventhough I'm having "multithreads" , all I'm using is one single thread at a time apart from the main thread because the port is being blocked.
What your friend told you is similar to passive FTP - a client tells the server that it needs a connection, the server sends back the port number and the client creates a data connection to that port.
But all you wanted to do is a multithreaded server. All you need is one server socket listening and accepting connections on a given port. As soon as the automatic TCP handshake is finished, you'll get a new socket from the accept function - that socket will be used for communication with the client that has just connected. So now you only have to create a new thread, passing that client socket to the thread function. In your server thread, you will then call accept again in order to accept another connection.
TCP/IP does the handshake, if you can't think of any reason to do a handshake than your application does not demand it.
An example of an application specific handshake could be for user authentication.
What your colleague is suggesting sounds like the way FTP works. This is not a good thing to do -- the internet these days is more or less used for protocols which use a single port, and having a command port is bad. One of the reasons is because statefull firewalls aren't designed for multi-port applications; they have to be extended for each individual application that does things this way.
Look at ASIO's tutorial on async TCP. There one part accept connections on TCP and spawns handlers that each communicate with a single client. That's how TCP-servers usually work (including HTTP/web, the most common tcp protocol.)
You may disregard the asynchronous stuff of ASIO if you're set on creating a thread per connection. It doesn't apply to your question. (Going fully async and have one worker-thread per core is nice, but it might not integrate well with the rest of your environment.)