Search code examples
c++socketstcpconnection-refused

TCP connection refused c++


I have problems connecting to my TCP server socket. I have had it working before, but after adding threads I had problems compiling it with just g++ main.cpp, and had to use a higher version, and after that it won't connect. The threads should really not mess with the execution of TCP connection. And it seems that it could be a compiler version or flag which is missing that could be the problem, but I'm not sure.

I have the firewall disabled, and have also tried with firewall on and accepting connections, but with no luck.

My client is returning the perror "Connection refused".

Wireshark packets show only two packets, which makes sense since the handshake is not complete.

wireshark image

I compile the server with g++ main.cpp -std=gnu++2a -pthread and run it with ./a.out, and compile the client with g++ testClientSocket.cpp -o testClient -std=gnu++2a -pthread and run it with ./testClient

The server is called in another file with code:

int main(){
    ServerSocket ss = ServerSocket(4000, "127.0.0.1");
}

The client is called in another file with:

int main(){
    SocketClient s = SocketClient(4000, "127.0.0.1");
} 

Server Code:

#include <sys/socket.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <unistd.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <mutex>
#include <thread>
#include "./Worker.cpp"

#include <vector>
using namespace std;

class ServerSocket{
public:
    ServerSocket(int PORT, string ip_address){
        Worker worker_threads(4);
        worker_threads.start(); // Create a worker loop

        mutex worker_lock; // Lock for avoiding race conditions.

        int serverFd = socket(AF_INET, SOCK_STREAM, 0); // File descriptor, -1 on error
        if(serverFd == -1) cerr << "Socket creation failed" << endl;
        bool runThreads = true;

        //Datastructure for storing address
        struct sockaddr_in server;

        int addressLength = sizeof(server);

        // reuse SOCKET AND ADDRESS/PORT
        int opt = 0;
        if(setsockopt(serverFd, SOL_SOCKET, SO_REUSEADDR , &opt, sizeof(opt))) perror("setsockopt failed");


        //Bind socket to port/ip
        bind(serverFd, (sockaddr*)&server, sizeof(server));


        //Initializes the address datastructure with appropriate addresses.
        server.sin_family = AF_INET;
        server.sin_addr.s_addr = INADDR_ANY;
        server.sin_port = htons(PORT);



        //Listen for incoming connections
        int listenStatus = listen(serverFd, SOMAXCONN);  //SOMAXCONN max queue length acc. to os.
        if(listenStatus == -1) perror("listen error");

        //Serves as event loop for server at this time. Will maybe change this later
        while(runThreads) {
            sockaddr_in client;
            socklen_t clientSize = sizeof(client);

            int new_socket = accept(serverFd, (struct sockaddr *)&client,(socklen_t*)&clientSize);
            if (new_socket == -1) perror("accept failed");
            else cout << "Connection established" << endl;
            cout << "after accept" << endl;

            connections.push_back(new_socket); //Push filedescriptor to connection to vector.

            threads.emplace_back([this, new_socket, &worker_threads, &worker_lock]{
                lock_guard<mutex> lock(worker_lock); // lock for code block
                //worker_threads.post() // POST WORK TO WORKER



            });


        }
    }

    void broadcastBallot(string message){
        //May need to message from string to bytes or something else for efficiency and logistics.

        //Connections only have filedescriptors
        //Send message to connected clients
        for(auto &con : connections){
            send(con, message.c_str() , strlen(message.c_str()) , 0 );
        }
    }

    void setCastedVotes(){
        //Readbuffer
        char readBuffer[1024] = {0};
        //May need a buffer for each connection, or use the same for all connections.

        for(auto &con :  connections){
            //Read incoming stream to bufferArray
            int readStatus  = read(con , readBuffer, 1024);
            cout << readStatus << endl;

            //Print out from readBuffer
            printf("%s\n", readBuffer );

            //TODO: SHOULD SET AN ARRAY OR SOMETHING
        }

    }


private:
    vector<int> connections;
    vector<thread> threads;



}; 

Client code:

#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <netinet/in.h>
#include <iostream>
#include <string>
#include <cstring>




using namespace std;


class SocketClient{
public:
    SocketClient(int PORT, string ip_addr){

        //Create socket
        int sock_fd = socket(AF_INET, SOCK_STREAM, 0);
        if(sock_fd == -1) cerr << "Socket creation failed" << endl;

        //For storing information about address and port etc.
        struct sockaddr_in address;

        //Initializing address etc.
        address.sin_family = AF_INET;
        address.sin_port = htons(PORT);
        inet_pton(AF_INET, ip_addr.c_str(), &address.sin_addr);


        //Connect to serversocket
        int connection = connect(sock_fd, (sockaddr*)&address, sizeof(address));
        if(connection == -1) {
            perror("Cannot connect\n");
        }

        string helloMsg = "hello";
        int sendResult = send(sock_fd, helloMsg.c_str(), helloMsg.size()+1,0);

        char readBuffer[1024];

        while(true){
            int readResult = recv(sock_fd, readBuffer, 1024,0);
            printf("%s\n", readBuffer );
        }


    }

private:


};

Solution

  • A bug here is that the server address is initialized after calling bind. So its content are undefined at that call (and thus depend on the compiler, the OS, and phase of Moon). Most likely that’s the problem.

    Also, SO_REUSEADDR is set to zero (which means FALSE) in the code; that’s probably not what was meant, and may cause problems on quick restart.