-1

I am coding a TCP client, and for every client's send function, I want to initiate a thread for that specific client's message or request being made. Meaning my program will have more than one client, each with its own send message thread, so I created a tcpClient object and each client object should have its own thread given to them when sending a message. My problem is I want the function that sends the message to be a member of the tcpClient object as well and passing this function into the std::thread function seems to not be possible. All my relevant code is shown below.

My header file:

//tcpClient.hpp

#include <iostream>
#include <functional>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>
#include <string>
#include <thread>

class tcpClient
{
    private:

        int sock;
        int port = 5400;
        int ipAddressInt[4] = {127, 0, 0, 1};;
        sockaddr_in hint;
        int connectRes;
        char buf[4096];
        int sendRes;
        int bytesReceived;
        bool sendLock;
        std::thread thread;

        
    public:

        bool Init ();
        bool SendThread ();
        void Send ();
};

My source code:

// tcpClient.cpp

#include "./hdr/tcpip_client.hpp"

using namespace std;
using namespace std::placeholders;

bool tcpClient::Init ()
{
    //  Create a socket
    sock = socket(AF_INET, SOCK_STREAM, 0);

    if (sock == -1)
    {
        return 0;
    }

    // Create a hint structure for the server we're connecting with
    string ipAddress = "";

    for (int i = 0; i <=3; i++)
    {
        if (i < 3) 
        {
            ipAddress = ipAddress + to_string(ipAddressInt[i]) + ".";
        }
        else
        {
            ipAddress = ipAddress + to_string(ipAddressInt[i]);
        }
    }

    hint.sin_family = AF_INET;
    hint.sin_port = htons(port);
    inet_pton(AF_INET, ipAddress.c_str(), &hint.sin_addr);

    //  Connect to the server on the socket
    connectRes = connect(sock, (sockaddr*)&hint, sizeof(hint));

    if (connectRes == -1)
    {
        return 0;
    }

    return 1;
}

bool tcpClient::SendThread ()
{
    // Enter lines of text
    cout << "> ";
    string userInput;
    getline(cin, userInput);

    // Send to server
    sendRes = send(sock, userInput.c_str(), userInput.size() + 1, 0);
    if (sendRes == -1)
    {
        cout << "Could not send to server! Whoops!\r\n";
        return 0;
    }

    // Wait for response
    memset(buf, 0, 4096);
    bytesReceived = recv(sock, buf, 4096, 0);

    if (bytesReceived == -1)
    {
        cout << "There was an error getting response from server\r\n";
    }

    else
    {
        // Display response
        cout << "SERVER> " << string(buf, bytesReceived) << "\r\n";
    }
    return 1;
}

void tcpClient::Send ()
{
    
    this->thread = std::thread(/*temp*/);
    this->thread.join();
}

So looking at the source file, at void tcpClient::Send () the /*temp*/ is a placeholder for what should be bool SendThread (). Please note that the networking part of my code is not the issue, only the fact that I can't seem to parse a function that is a member of the class is what I am struggling with.

Thanks for any help.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • 2
    Use a lambda function. `m_future = std::async(std::launch::async, [&]{ tcpClient.SendThread(); });`. I find futures play nice with RAII and automic synchronization with the end of the thread. Make m_future a member of your class and your class destructor will syncrhonize with the end of the asynchronous call. – Pepijn Kramer Jan 26 '23 at 11:09

1 Answers1

3

First of all, you need to pass the object to call the function on (this) as an argument.

Secondly you need to pass an explicit pointer (with the pointer-to operator &) for the function to call.

As shown in countless examples all over the Internet:

thread = std::thread(&tcpClient::SendThread, this);

With that said, there are a couple of issues:

First of all, calling join directly doesn't run the thread in parallel, it's just like just plain calling the function.

Secondly, thread functions should not return a value.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621