C++ thread-per-request chat on linux with sockets and multiple clients - c++

we are learning how to work with sockets and threads and are trying to make a simple chat program. Multiple clients can successfully connect and all of them can receive messages, but only the first connecting client can send messages.
So client nr 1 completely works, and all others can only receive but not send to the server.
All threads are running like we think they should, but only the first receiving thread is able to read from the receive queue.
with netstat we can see that the message queue of the second client is full
screenshot from netstat
#include <iostream>
#include "socket.hpp"
#include <string>
#include <queue>
#include <unistd.h>
using namespace std;
int clients[100];//All Clientnumbers
int i=0;//Number of connected Clients
Socket* sockArray[100];
Socket* sockArray2[100];
queue<string> nachrichten;//message queue
void *empfangen(void* x);
void *tpr(void* servsockp);
int main()
{
cout << "Hello, World! Server startet" << endl;
ServerSocket servSock(6200, 1000);//start Serversocket
ServerSocket *servsockp = &servSock;
pthread_t tpr_starter;//new thread that creates tpr
pthread_create(&tpr_starter, NULL, tpr,(void*)servsockp);
while(true) //if there are messages in the queue send them to all clients
{
if(nachrichten.size()!=0)
{
for (int y = 0; y < i; y++)
{
try
{
cout<< "Gesendet: " << nachrichten.front() <<clients[0]<<clients[1]<<i<< endl;
(*sockArray[y]).send(nachrichten.front());
} catch (SocketException e) {
cout << e.getError() << endl;
}
}
nachrichten.pop();
}
}
pthread_join(tpr_starter, NULL);
}
void*tpr(void* servsockp)//open socket for every request, start new receiving thread
{
while(true)
{
clients[i]= (*(ServerSocket*)(servsockp)).accept();
int*x =new int(i);
Socket *sock = new Socket(clients[i]);
sockArray[i]=sock;
sockArray2[i]=sock;
i++;
sleep(2);
pthread_t rec;
pthread_create (&rec, NULL, empfangen, (void*)x);
}
}
void *empfangen(void* x)//listening on new socket, put received messages in queue
{
int number=*(int*)x;
cout <<"Receiving/thread started on Socket Nr: "<< number<<endl;
while(true){
try {
string nachricht = (*sockArray2)[number].recv();
if(nachricht=="")
{
break;
}
cout <<"Received: "<< nachricht << endl;
nachrichten.push(nachricht);
}catch(SocketException e){
cout << e.getError()<<endl;
}
}
}
Can anyone tell if we are on the right way or if we are doing something completely wrong?
Thank you!

Today my professor found the solution:
(*sockArray2)[number].recv();
this line is absolutely wrong, it has to be
sockArray2[number]->recv();

Related

Read/print socket ouput while waiting on cin (w/o multithreading)

i have a client program that connects to a server via a TCP socket, below:
int main ( )
{
std::cout << "HunterChat client starting up" << std::endl;
std::string cmd;
std::string reply;
bool cont = true;
ClientSocket client_socket ( "localhost", PORT );
try {
while(cont) {
try {
std::cout << ">> ";
// std::getline(std::cin,cmd);
gets(cmd);
if(cmd.compare("logout") == 0) {
cont = false;
break;
}
client_socket << cmd;
client_socket >> reply;
std::cout << reply << std::endl;
}
catch ( SocketException& e) {
std::cout << "Exception was caught:" << e.description() << "\n";
}
}
}
catch ( SocketException& e ) {
std::cout << "Exception was caught:" << e.description() << "\n";
}
return 0;
}
ClientSocket is a custom class that lets me set up and use the TCP connection; the stream operator is overloaded with, the following code:
int status = ::send ( m_sock, s.c_str(), s.size(), MSG_NOSIGNAL );
if ( status == -1 )
{
return false;
}
else
{
return true;
}
The TCP connection itself is working fine, so I won't clutter the post up with more of it. The problem is that one of the available commands involves sending input to a client instance while said client is still waiting for cin input. This means that the server messages only get read and written when I type something into cin. I'm trying to avoid using multithreading, so is there any way to allow cin to be interrupted without it?
Well, you could use a loop and the function kbhit() to check for user input if you really want to. However, threading seems to me such a better solution.
#include <conio.h>
#include <iostream>
using namespace std;
int main()
{
while(1)
{
if(kbhit())
{
char x = getch();
// ...
}
// check messages asynchronously here
}
}

MHD_resume_connection() of libmicrohttpd not working properly with external select

I encountered some problems with MHD_suspend_connection() and MHD_resume_connection() in libmicrohttpd while using the external event loop. Afterwards I have wrote a small example (without error handling) below. My question is: What am I doing wrong? Or is it a bug in the library? It should work as far as I understand the manual. Using external select with suspend/resume is allowed explicitly.
The problem is that connections are not resumed correctly. Processing the connection does not continue right after calling MHD_resume_connection(). In some versions of my program, it did continue after another request was incomming. In other versions later requests was not handled at all (access_handler() was never called). In some of this versions I got a response for the first request while stopping libmicrohttpd. When I enable MHD_USE_SELECT_INTERNALLY and remove my external loop (let it sleep), everything works.
I tested it on Debian (libmicrohttpd 0.9.37) and Arch (libmicrohttpd 0.9.50). The problem exists on both systems but maybe the behavior was a little bit different.
#include <algorithm>
#include <csignal>
#include <cstring>
#include <iostream>
#include <vector>
#include <sys/select.h>
#include <microhttpd.h>
using std::cerr;
using std::cout;
using std::endl;
static volatile bool run_loop = true;
static MHD_Daemon *ctx = nullptr;
static MHD_Response *response = nullptr;
static std::vector<MHD_Connection*> susspended;
void sighandler(int)
{
run_loop = false;
}
int handle_access(void *cls, struct MHD_Connection *connection,
const char *url, const char *method, const char *version,
const char *upload_data, size_t *upload_data_size,
void **con_cls)
{
static int second_call_marker;
static int third_call_marker;
if (*con_cls == nullptr) {
cout << "New connection" << endl;
*con_cls = &second_call_marker;
return MHD_YES;
} else if (*con_cls == &second_call_marker) {
cout << "Suspending connection" << endl;
MHD_suspend_connection(connection);
susspended.push_back(connection);
*con_cls = &third_call_marker;
return MHD_YES;
} else {
cout << "Send response" << endl;
return MHD_queue_response(connection, 200, response);
}
}
void myapp()
{
std::signal(SIGINT, &sighandler);
std::signal(SIGINT, &sighandler);
ctx = MHD_start_daemon(MHD_USE_DUAL_STACK //| MHD_USE_EPOLL
| MHD_USE_SUSPEND_RESUME | MHD_USE_DEBUG,
8080, nullptr, nullptr,
&handle_access, nullptr,
MHD_OPTION_END);
response = MHD_create_response_from_buffer(4, const_cast<char*>("TEST"),
MHD_RESPMEM_PERSISTENT);
while (run_loop) {
int max;
fd_set rs, ws, es;
struct timeval tv;
struct timeval *tvp;
max = 0;
FD_ZERO(&rs);
FD_ZERO(&ws);
FD_ZERO(&es);
cout << "Wait for IO activity" << endl;
MHD_UNSIGNED_LONG_LONG mhd_timeout;
MHD_get_fdset(ctx, &rs, &ws, &es, &max);
if (MHD_get_timeout(ctx, &mhd_timeout) == MHD_YES) {
//tv.tv_sec = std::min(mhd_timeout / 1000, 1ull);
tv.tv_sec = mhd_timeout / 1000;
tv.tv_usec = (mhd_timeout % 1000) * 1000;
tvp = &tv;
} else {
//tv.tv_sec = 2;
//tv.tv_usec = 0;
//tvp = &tv;
tvp = nullptr;
}
if (select(max + 1, &rs, &ws, &es, tvp) < 0 && errno != EINTR)
throw "select() failed";
cout << "Handle IO activity" << endl;
if (MHD_run_from_select(ctx, &rs, &ws, &es) != MHD_YES)
throw "MHD_run_from_select() failed";
for (MHD_Connection *connection : susspended) {
cout << "Resume connection" << endl;
MHD_resume_connection(connection);
}
susspended.clear();
}
cout << "Stop server" << endl;
MHD_stop_daemon(ctx);
}
int main(int argc, char *argv[])
{
try {
myapp();
} catch (const char *str) {
cerr << "Error: " << str << endl;
cerr << "Errno: " << errno << " (" << strerror(errno) << ")" << endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
I've compiled and run your sample on Windows and am seeing the same behavior w/ 0.9.51.
It's not a bug in microhttpd. The problem is that you are resuming a connection before queuing a response on it. The only code you have that creates a response relies on more activity on the connection so it's a catch-22.
The point of MHD_suspend_connection/MHD_resume_connection is to not block new connections while long-running work is going on. Thus typically after suspending the connection you need to kick off that work on another thread to continue while the listening socket is maintained. When that thread has queued the response it can resume the connection and the event loop will know it is ready to send back to the client.
I'm not sure of your other design requirements but you may not need to be implementing external select. That is to say, suspend/resume does not require it (I've used suspend/resume just fine with MHD_USE_SELECT_INTERNALLY, e.g.).
I dont know if it's mentioned. But you have a multi-threading bug, and perhaps, "intent bug". As the lib, may or may not use threads, depending on other factors. You can see if you are using threads, by printing the thread id, from the functions. But, your answerToConnection function, sets your vector (without mutex protection), and then you are immediately looking at it, and retrying potentially from another thread. this goes against the intent/purpose of suspend/retry, since suspend is really for something taking "a long time". The gotcha, is that you dont own the calling code, so, you dont know when it's totally done. however, you can age your retry, with a timeval, so, you dont retry too soon. at least a value of tv_usec +1. you need to note, that you are using the vector from two or more threads, without mutex protection.

ZeroMq PUB/SUB pattern not working properly

My Requirements:
High throughput, atleast 5000 messages per second
Order of delivery not important
Publisher, as obvious, should not wait for a response and should not care if a Subscriber is listening or not
Background:
I am creating a new thread for every message because if I dont, the messages generation part will out-speed the sending thread and messages get lost, so a thread for each message seems to be the right approach
Problem:
The problem is that somehow the threads that are started to send out the zMQ message are not being terminated (not exiting/finishing). There seems to be a problem in the following line:
s_send(*client, request.str());
because if I remove it then the threads terminate fine, so probably its this line which is causing problems, my first guess was that the thread is waiting for a response, but does a zmq_PUB wait for a response?
Here is my code:
void *SendHello(void *threadid) {
long tid;
tid = (long) threadid;
//cout << "Hello World! Thread ID, " << tid << endl;
std::stringstream request;
//writing the hex as request to be sent to the server
request << tid;
s_send(*client, request.str());
pthread_exit(NULL);
}
int main() {
int sequence = 0;
int NUM_THREADS = 1000;
while (1) {
pthread_t threads[NUM_THREADS];
int rc;
int i;
for (i = 0; i < NUM_THREADS; i++) {
cout << "main() : creating thread, " << i << endl;
rc = pthread_create(&threads[i], NULL, SendHello, (void *) i);
pthread_detach(threads[i]);
sched_yield();
if (rc) {
cout << "Error:unable to create thread," << rc << endl;
exit(-1);
}
}
//usleep(1000);
sleep(1);
}
pthread_exit(NULL);
//delete client;
return 0;
}
My Question:
Do I need to tweak zMQ sockets so that the PUB doesnt wait for a reply what am I doing wrong?
Edit:
Adding client definition:
static zmq::socket_t * s_client_socket(zmq::context_t & context) {
std::cout << "I: connecting to server." << std::endl;
zmq::socket_t * client = new zmq::socket_t(context, ZMQ_SUB);
client->connect("tcp://localhost:5555");
// Configure socket to not wait at close time
int linger = 0;
client->setsockopt(ZMQ_LINGER, &linger, sizeof (linger));
return client;
}
zmq::context_t context(1);
zmq::socket_t * client = s_client_socket(context);
but does a zmq_PUB wait for a response?
No, this could be the case if your socket wasn't a PUB socket and you hit the high-water mark, but this isn't the case. Do the messages get sent?

SFML TCP packet receive

I send a packet as client to server and I want to the server sends that packet forward to all client, here is the code:
#include <iostream>
#include <SFML/Network.hpp>
using namespace std;
int main()
{
int fromID; // receive data from 'fromID'
int Message; // fromID's message
sf::SocketTCP Listener;
if (!Listener.Listen(4567))
return 1;
// Create a selector for handling several sockets (the listener + the socket associated to each client)
sf::SelectorTCP Selector;
Selector.Add(Listener);
while (true)
{
unsigned int NbSockets = Selector.Wait();
for (unsigned int i = 0; i < NbSockets; ++i)
{
// Get the current socket
sf::SocketTCP Socket = Selector.GetSocketReady(i);
if (Socket == Listener)
{
// If the listening socket is ready, it means that we can accept a new connection
sf::IPAddress Address;
sf::SocketTCP Client;
Listener.Accept(Client, &Address);
cout << "Client connected ! (" << Address << ")" << endl;
// Add it to the selector
Selector.Add(Client);
}
else
{
// Else, it is a client socket so we can read the data he sent
sf::Packet Packet;
if (Socket.Receive(Packet) == sf::Socket::Done)
{
// Extract the message and display it
Packet >> Message;
Packet >> fromID;
cout << Message << " From: " << fromID << endl;
//send the message to all clients
for(unsigned int j = 0; j < NbSockets; ++j)
{
sf::SocketTCP Socket2 = Selector.GetSocketReady(j);
sf::Packet SendPacket;
SendPacket << Message;
if(Socket2.Send(SendPacket) != sf::Socket::Done)
cout << "Error sending message to all clients" << endl;
}
}
else
{
// Error : we'd better remove the socket from the selector
Selector.Remove(Socket);
}
}
}
}
return 0;
}
Client code:
in Player class I have this function :
void Player::ReceiveData()
{
int mess;
sf::Packet Packet;
if(Client.Receive(Packet) == sf::Socket::Done)
{
Client.Receive(Packet);
Packet >> mess;
cout << mess << endl;
}
}
main.cpp:
Player player;
player.Initialize();
player.LoadContent();
player.Connect();
..
..
//GAME LOOP
while(running==true)
{
sf::Event Event;
while(..) // EVENT LOOP
{
...
}
player.Update(Window);
player.ReceiveData();
player.Draw(Window);
}
When I run this client code, the program not responding, freezes.
The problem is with that ReceiveDate() function.
All sockets, even the one created by SFML, are by default blocking. This means that when you try to receive when there is nothing to receive, the call will block, making your application seem "freezed".
You can toggle the blocking status of a SFML socket with the sf::SocketTCP::SetBlocking function.
The problem with sending to all clients failing is because you use GetSocketReady to get the clients to send to. That function only returns a socket for clients that are ready (i.e. the previous call to Wait marked the socket as having input).
You need to refactor the server to keep track of the connected clients in another way. The common way is to reset and recreate the selector every time in the outer loop, and have a separate collection of the connected clients (e.g. a std::vector).

Make socket server accept multiple clients

I'd like to change the socket class I am using to accept an infinite amount of clients. At the moment it allows one client, and once that client disconnect the server exits.
#include "stdafx.h"
#include "mySocket.h"
#include "myException.h"
#include "myHostInfo.h"
void main()
{
#ifdef WINDOWS_XP
// Initialize the winsock library
WSADATA wsaData;
try
{
if (WSAStartup(0x101, &wsaData))
{
myException* initializationException = new myException(0,"Error: calling WSAStartup()");
throw initializationException;
}
}
catch(myException* excp)
{
excp->response();
delete excp;
exit(1);
}
#endif
// get local server information
myHostInfo uHostAddress;
string localHostName = uHostAddress.getHostName();
string localHostAddr = uHostAddress.getHostIPAddress();
cout << "------------------------------------------------------" << endl;
cout << " My local host information:" << endl;
cout << " Name: " << localHostName << endl;
cout << " Address: " << localHostAddr << endl;
cout << "------------------------------------------------------" << endl;
// open socket on the local host
myTcpSocket myServer(PORTNUM);
cout << myServer;
myServer.bindSocket();
cout << endl << "server finishes binding process... " << endl;
myServer.listenToClient();
cout << "server is listening to the port ... " << endl;
// wait to accept a client connection.
// processing is suspended until the client connects
cout << "server is waiting for client connecction ... " << endl;
myTcpSocket* client; // connection dedicated for client communication
string clientHost; // client name etc.
client = myServer.acceptClient(clientHost);
cout << endl << "==> A client from [" << clientHost << "] is connected!" << endl << endl;
while(1)
{
//Send message to the client
client->sendMessage(std::string("Test"));
// receive from the client
string clientMessageIn = "";
int numBytes = client->recieveMessage(clientMessageIn); //Get message from client, non-blocking using select()
if ( numBytes == -99 ) break;
if(clientMessageIn != "")
{
std::cout << "received: " << clientMessageIn << std::endl; //What did we receive?
/* Do somethign with message received here */
}
}
#ifdef WINDOWS_XP
// Close the winsock library
try
{
if (WSACleanup())
{
myException* cleanupException = new myException(0,"Error: calling WSACleanup()");
throw cleanupException;
}
}
catch(myException* excp)
{
excp->response();
delete excp;
exit(1);
}
#endif
}
How do I change the main() function so that it is constantly waiting for new clients to connect, and once they do, create a new thread for him (the client), or a new handler socket (whatever that may be).
I did find this thread to be informative, but I lack the required knowledge of sockets to actually implement it in the above code.
The answer states When doing socket communication, you basically have a single listener socket for all incoming connections, and multiple handler sockets for each connected client.
So I am guessing in my code;
myTcpSocket myServer(PORTNUM);
myServer.bindSocket();
myServer.listenToClient();
Would be the listener socket
But where/how would I fork the client who is connecting off to a handler socket ?
I am sorry for not being able to show more effort on my part, I don't like coming across as lazy. But for all the hours I have searched and the trial and error resulting from that, I don't have much to show for it.
The idea is simple, you just wait for incoming connections, and once accepted, pass the socket to a thread.
You need to pass the new socket returned from accept to the new thread; you could either spawn a new thread everytime and pass the socket via argument or add the socket to a shared queue used by a bunch of worker threads.
Here's some code for a simple proxy I wrote, it uses boost for the threads and a simple OOP wrapper around the socket functions.
The main thread - it creates 4 worker threads which idle and wait for
the semaphore to be signalled. It pushes all accepted connections to a global queue:
// Global variables
const size_t MAX_THREADS = 4;
queue<Socket> socketBuffer; // Holds new accepted sockets
boost::mutex queueGuard; // Guards the socketBuffer queue
semaphore queueIndicator; // Signals a new connection to the worker threads
bool ctrlc_pressed = false;
// Inside the main function...
boost::thread_group threads;
for(int i = 0; i < MAX_THREADS; i++)
{
threads.create_thread(boost::bind(&threadHandleRequest, i+1));
}
while(!ctrlc_pressed)
{
// wait for incoming connections and pass them to the worker threads
Socket s_connection = s_server.accept();
if(s_connection.valid())
{
boost::unique_lock<boost::mutex> lock(queueGuard);
socketBuffer.push(s_connection);
queueIndicator.signal();
}
}
threads.interrupt_all(); // interrupt the threads (at queueGuard.wait())
threads.join_all(); // wait for all threads to finish
s_server.close();
And the thread code:
bool threadHandleRequest(int tid)
{
while(true)
{
// wait for a semaphore counter > 0 and automatically decrease the counter
try
{
queueIndicator.wait();
}
catch (boost::thread_interrupted)
{
return false;
}
boost::unique_lock<boost::mutex> lock(queueGuard);
assert(!socketBuffer.empty());
Socket s_client = socketBuffer.front();
socketBuffer.pop();
lock.unlock();
// Do whatever you need to do with the socket here
}
}
Hope that helps :)
When doing socket communication, you basically have a single listener
socket for all incoming connections, and multiple handler sockets for
each connected client.
That's the point. You need a separate thread for the listener socket. When it receives an incoming request, it starts another thread for a handler socket (which will create and send the response), and starts listening again (you need a loop).
I would definitely use threads instead of forking. AFAIK on Windows only cygwin is able to fork, but I would not use cygwin for such a program.