C++ Implementing threads with Inter thread communication - c++

im currently attempting to create server and client application that use winsock, with a main program I need to have a second thread to always be listening for data.
This communication is non blocking. I am really having trouble in finding a way of communicating between threads, an example of what im looking for is: Server sends a string to the client e.g. "viewData" and this kind of information will be fetched by the main thread and then a specific function may also be called.
Here is an example of my thread, i am creating this using _beginthread( (void(*)(void*))SocketReceive, 0, (void*)&ohuman );
//thread focused on listening to connection
void SocketReceive( comms* ohuman)
{
char buffer[1000];
int inDataLength;
std::string contents;
for(;;)
{
if(!ohuman->getGameOn())
{
// Display message from server
memset(buffer,0,999);
inDataLength=recv((INT_PTR)ohuman->getSocket(),buffer,1000,0);
contents = std::string(buffer); //create a string from the char array for easy access
//only display if we get some content
if(inDataLength > 0)
{
//???DealWithMessage(
int nError=WSAGetLastError();
if(nError!=WSAEWOULDBLOCK&&nError!=0)
{
std::cout<<"Winsock error code: "<<nError<<"\r\n";
std::cout<<"Server disconnected!\r\n";
// Shutdown our socket
shutdown((INT_PTR)ohuman->getSocket(),0x01);
// Close our socket entirely
closesocket((INT_PTR)ohuman->getSocket());
break;
}
}
}
_endthread();
}
I also saw this site which is supposed to help out with ITC, any advice on this->
http://derkarl.org/itc/
With a straightforward main loop, I am interested in any approach that might work, I've been trying to figure this out for a couple of days with no luck, any help is greatly appreciated.

You can either have a shared variable(with locks around it) and both threads poll/write to it, or you can register callback functions between the threads and call the other thread on some event.

Related

Async C++ socket

I am trying to write an asynchronous server to handle multiple users at the same time. The server is standing in the main thread listening for receiving data, in the same thread it receives them (large images) and creates a task to process this data, which it sends to the thread pool, and itself listens to the next image. Here is the code (Handle contains data processing that is performed on another thread):
while (true) {
cv::Mat data = ReceiveImage();
m_Pool.AddTask([=]() mutable {
Handle(std::move(data));
});
}
cv::Mat UDPServer::ReceiveImage() const {
...
try {
for (int i = 0; i < sz; i += num_bytes) {
num_bytes = ReceiveData((char*)&buf[0] + i, sz - i, from);
}
}
...
}
int UDPServer::ReceiveData(char* buf, int len, sockaddr_in& from) const {
socklen_t slen = sizeof(from);
int nReceivedBytes = recvfrom(m_Socket, buf, len, 0, (sockaddr*)&from, &slen);
if (nReceivedBytes == SOCKET_ERROR) {
throw std::runtime_error(RECEIVEFROM_ERROR.data());
}
return nReceivedBytes;
}
There is a problem with this approach: while accepting data from one user, another user can send his data, which will not be accepted.
A possible solution is to accept the data on a different thread. To do this, I want to receive ONLY a signal in the main thread that data has arrived, and transfer them to another thread to receive and send them to the thread pool. Something like Probe in MPI.
How can this be implemented on C ++ sockets? I tried to find it on the internet, but nothing came of it. Or does anyone have a better solution to the problem?
TCP sockets work this way. There is a listened-to socket, call it P, and an actual communication socket, call it Q. The accept system call does this:
Q = accept(P, ...); // there are other parameters
// which are not important here
As soon as accept returns, you can launch an async task on Q, and continue listening on P. The two jobs will not interfere with each other. If another request comes why you are still grinding away on Q, accept will just return another Q for another async task.
This whole idea doesn't work all that well for UDP because there are no persistent connections. Each packet is a communication session of its own. It doesn't make a lot of sense to asynchronously read a packet from a socket. Reading is an atomic operation, and packets are short enough. You can launch an asynchronous task to process each packet's data, there's nothing wrong with that. You can try to implement asynchronous reading by polling on a socket and launching an async task that reads the data as soon as it's ready, but this won't really simplify or speed up anything.

Passing data to another thread in a C++ winsock app

So I have this winsock application (a server, able to accept multiple clients), where in the main thread I setup the socket and create another thread where I listen for clients (listen_for_clients function).
I also constantly receive data from a device in the main thread, which I afterwards concatenate to char arrays (buffers) of Client objects (BroadcastSample function). Currently I create a thread for each connected client (ProcessClient function), where I initialize a Client object and push it to a global vector of clients after which I send data to this client through the socket whenever the buffer in the corresponding Client object exceeds 4000 characters.
Is there a way I can send data from the main thread to the separate client threads so I don't have to use structs/classes (also to send a green light if I want to send the already accumulated data) and also if I'm going to keep a global container of objects, what is a good way to remove a disconnected client object from it without crashing the program because another thread is using the same container?
struct Client{
int buffer_len;
char current_buffer[5000];
SOCKET s;
};
std::vector<Client*> clientBuffers;
DWORD WINAPI listen_for_clients(LPVOID Param)
{
SOCKET client;
sockaddr_in from;
int fromlen = sizeof(from);
char buf[100];
while(true)
{
client = accept(ListenSocket,(struct sockaddr*)&from,&fromlen);
if(client != INVALID_SOCKET)
{
printf("Client connected\n");
unsigned dwThreadId;
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, &ProcessClient, (void*)client, 0, &dwThreadId);
}
}
closesocket(ListenSocket);
WSACleanup();
ExitThread(0);
}
unsigned __stdcall ProcessClient(void *data)
{
SOCKET ClientSocket = (SOCKET)data;
Client * a = new Client();
a->current_buffer[0] = '\0';
a->buffer_len = 0;
a->s = ClientSocket;
clientBuffers.push_back(a);
char szBuffer[255];
while(true)
{
if(a->buffer_len > 4000)
{
send(ClientSocket,a->current_buffer,sizeof(a->current_buffer),0);
memset(a->current_buffer,0,5000);
a->buffer_len = 0;
a->current_buffer[0] = '\0';
}
}
exit(1);
}
//function below is called only in main thread, about every 100ms
void BroadcastSample(Sample s)
{
for(std::vector<Client*>::iterator it = clientBuffers.begin(); it != clientBuffers.end(); it++)
{
strcat((*it)->current_buffer,s.to_string);
(*it)->buffer_len += strlen(s.to_string);
}
}
This link has some Microsoft documentation on MS-style mutexes (muticies?).
This other link has some general info on mutexes.
Mutexes are the general mechanism for protecting data which is accessed by multiple threads. There are data structures with built-in thread safety, but in my experience, they usually have caveats that you'll eventually miss. That's just my two cents.
Also, for the record, you shouldn't use strcat, but rather strncat. Also, if one of your client servicing threads accesses one of those buffers after strncat overwrites the old '\0' but before it appends the new one, you'll have a buffer overread (read past end of allocated buffer).
Mutexes will also solve your current busy-waiting problem. I'm not currently near a windows compiler, or I'd try to help more.

edited: accessing a method in a running c++ program

I need to make a statistical printout of a socket program.
I am using method Listen(uint32_t port) in c++ thread to listen to clients on the specified port (more than one) and send/receive client's transactions to/from a server.
Now i need to write a log file of how many packet received/sent by this method.
my implementation is shown in the skeleton below:
hub.cpp
//set up necessary header
#include <iostream>
....
#include <vector>
//global variables
std::map<uint32_t,long> * received_pk;
std::map<uint32_t,long> * sent_pk;
void Listen(uint32_t port ); // method
int main (int argc, char **argv){
//set up client ports
vector<uint32_t> client_ports;
client_ports.push_back(50002);
client_ports.push_back(50003);
//initialize variables
received_pk = new std::map<uint32_t,uint32_t>();
sent_pk = new std::map<uint32_t,uint32_t>();
for(uint32_t i=0;i<client_ports.size();i++){
received_pk->insert(std::pair<uint32_t,uint32_t>(client_ports.at(i),0) );
sent_pk->insert(std::pair<uint32_t,uint32_t>(client_ports.at(i),0) );
}
//set up thread
vector<thread*> threads;
for(uint32_t i=0;i<client_ports.size();i++){
cout << "Create Listener in port " << client_ports.at(i) << endl;
threads.push_back(new thread(Listen,client_ports.at(i)));
}
//Wait for the threads to finish
for(uint32_t i=0;i<client_ports.size();i++){
threads.at(i)->join();
}
}
void Listen(uint32_t port){
...
set up struct sockaddr_in client, host;
listen on port: port
...
while(1){
receive packet from client;
received_pk->at(port)++;
check packet type
if(packet==status packet){
update the packet id number
}
if (packet==transaction){
send packet to Server
receive reply
send reply back to client
sent_pk->at(port)++;
}
}
}
Now i need to access received_pk and sent_pk while hub.cpp is still running (probably in the while loop)
I thought of two options:
Access received_pk and sent_pk from an external program: like define a method that can get the packet information while the thread is till running
problem: I don't know if i can access a variable/method while program is executing .
or print received_pk and sent_pk to a log file every 5 seconds.
problem: I don't know if it makes sense to have a timer in the multiple thread.
Please any advice will be appreciated.
Kehinde
Quite possibly, the easiest solution is to put the data in shared memory. The map x is a bit suspect - did you mean std::map<Key, Value>? That doesn't fit well in shared memory. Instead, use simple arrays. There are just 64K ports, and sizeof(long long[65536]) isn't excessive.

C++ - Sockets and multithreading

Socket A(local_address);
void enviar(sockaddr_in remote_address, std::atomic<bool>& quit){
std::string message_text;
Message message;
while(!quit){
std::getline(std::cin, message_text);
if (message_text != "/quit"){
memset(message.text, 0, 1024);
message_text.copy(message.text, sizeof(message.text) - 1, 0);
A.send_to(message, remote_address);
}
else {
quit = true;
}
}
}
void recibir(sockaddr_in local_address, std::atomic<bool>& quit){
Message messager;
while(!quit){
A.receive_from(messager, local_address);
}
}
int main(void){
std::atomic<bool> quit(false);
sockaddr_in remote_address = make_ip_address("127.0.0.1",6000);
std::thread hilorec(&recibir,local_address, std::ref(quit));
std::thread hiloenv(&enviar,remote_address, std::ref(quit));
hiloenv.join();
hilorec.join();
}
Hi! I'm trying to make a simple chat with sockets. I want the program to finish when I write "/quit". I'm trying this with an atomic bool variable called quit. The problem is when I write "/quit" quit will be 'true' and the hiloenv thread will be finish, but hilorec, which is to receive the messages, will be blocked until i receive a message because of the recvfrom() function. How i can solve this?
Sorry for my english and thanks!
Shutdown the socket for input. That will cause recvfrom() to return zero as though the peer had closed the connection, which will cause that thread to exit.
I would send some special (e.g. empty) message to A socket from main thread when quit is detected. In this case your while(!quit) ... loop will finish and so the thread.
If you want to create a single thread app, then use epoll or select apis. If you want to stick to your current design, then you can create your socket having timeout set. Please look for How to set socket timeout in C when making multiple connections? for details. SO when you do quit, the waiting thread will come out of recv or send after the timout and then thread will join and your application can quit gracefully.
Thanks for the answers. I managed to fix it, If anyone is interested how:
std::thread hilorec(&recibir,local_address);
std::thread hiloenv(&enviar,remote_address);
while(!quit){}
pthread_cancel(hilorec.native_handle());
pthread_cancel(hiloenv.native_handle());
hilorec.join();
hiloenv.join();

Handling threads in server application after clients disconnect

I'm currently working on simple HTTP server. I use Winsock and standard threads from C++11. For each connected (accepted) client there is new thread created.
std::map<SOCKET, std::thread> threads;
bool server_running = true;
while(server_running) {
SOCKET client_socket;
client_socket = accept(listen_socket, NULL, NULL);
if(client_socket == INVALID_SOCKET) {
// some error handling
}
threads[client_socket] = std::thread(clientHandler, client_socket);
}
clientHandler function looks generally like this:
while(1) {
while(!all_data_received) {
bytes_received = recv(client_socket, recvbuf, recvbuflen, 0);
if(bytes_received > 0) {
// do something
} else {
goto client_cleanup;
}
}
// do something
}
client_cleanup: // we also get here when Connection: close was received
closesocket(client_socket);
And here we come to my problem - how to handle all the threads which ended but haven't been joined with main thread and references to them still exist in threads map?
The simplest solution would be probably to iterate over threads frequently (e.q. from another thread?) and join and delete those which returned.
Please share your expertise. :)
PS. Yes, I know about thread pool pattern. I'm not using it in my app (for better or worse). I'm looking for answer concerning my current architecture.
Simple solution? Just detach() after you start the thread. This will mean that once the thread terminates the resources will be cleaned up and you don't need to keep the std::map<SOCKET, std::thread> threads.
std::thread(clientHandler, client_socket).detach();
Otherwise create a thread-safe LIFO queue where during cleanup you push the socket to it.
Then in the main loop you alternately check accept and that queue and when the queue has sockets in them you do threads.erase(socket); for each socket in the queue.
However if you do that then you may as well putt he LIFO in the other direction and use a thread pool.