TCP-соединение отказано c ++ - PullRequest
0 голосов
/ 15 апреля 2020

У меня проблемы с подключением к сокету TCP-сервера. Раньше у меня это работало, но после добавления потоков у меня были проблемы с компиляцией с g++ main.cpp, и мне пришлось использовать более высокую версию, и после этого она не подключалась. Потоки действительно не должны связываться с выполнением соединения TCP. И кажется, что это может быть версия или флаг компилятора, который отсутствует, что может быть проблемой, но я не уверен.

У меня отключен брандмауэр, а также пробовал с включенным брандмауэром и принятием соединений , но безуспешно.

Мой клиент возвращает перрор "Отказано в соединении".

Пакеты Wireshark показывают только два пакета, что имеет смысл, поскольку квитирование не завершено.

wireshark image

Я компилирую сервер с g++ main.cpp -std=gnu++2a -pthread, запускаю с ./a.out, компилирую клиент с g++ testClientSocket.cpp -o testClient -std=gnu++2a -pthread и запускаю с ./testClient

Сервер вызывается в другом файле с кодом:

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

Клиент вызывается в другом файле с:

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

Код сервера:

#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;



}; 

Код клиента:

#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:


};

1 Ответ

1 голос
/ 16 апреля 2020

Ошибка здесь в том, что адрес сервера инициализируется после вызова bind. Таким образом, его содержимое не определено при этом вызове (и, таким образом, зависит от компилятора, ОС и фазы Луны). Скорее всего, это проблема.

Кроме того, SO_REUSEADDR устанавливается в ноль (что означает ЛОЖЬ) в коде; это, вероятно, не то, что имелось в виду, и может вызвать проблемы при быстром перезапуске.

...