Wielowątkowy socket pod linuxem c++ 11 std::thread

W tym miejscu zadajemy pytania na temat języka C++, dzielimy się swoją wiedzą, udzielamy wsparcia, rozwiązujemy problemy programistyczne.
Awatar użytkownika
edwardkraweznik
Posty: 3
Rejestracja: wtorek 20 kwie 2021, 07:27

Wielowątkowy socket pod linuxem c++ 11 std::thread

Postautor: edwardkraweznik » sobota 24 kwie 2021, 22:28

Witam wszystkich.
Poniżej przedstawiam wielowątkowy socket c++ 11 OOP. Gniazdo w systemie Linux
Komus może się przydać.

W poniższym kodzie jest błąd (należy użyć vector przy deskryptorze a także usuwać nieaktywne połączenia) <--- każdy powinien sobie to ogarnąć samodzielnie.

main.cpp

Kod: Zaznacz cały

#include "main.hpp"

#define MAX_MSG_LEN 4096
#define SERWER_PORT 8888
#define SERWER_IP "127.0.0.1"
#define MAX_CONNECTION 10

int main()
{
    ServerSock ss;

    int i = 0;

    while(true)
    {
        struct sockaddr_in client = { };

        int new_sock[2048];

        new_sock[i] = accept( ss.sock,( struct sockaddr * ) & client, & ss.len );

        if( new_sock[i] < 0 )
        {
            if( errno == EWOULDBLOCK )
            {
                //std::cout << "nconn" << std::endl;
                std::this_thread::sleep_for(std::chrono::milliseconds(5));
                continue;
            }

            else
            {
                std::cout << "err:main:1:socket create" << std::endl;
                return(0);
            }
        }

        //---------------------------------------------------------

        else
        {

            ClientSock ppp(new_sock[i]);
            i++;
        }

        //---------------------------------------------------------


    }
}

//eof



main.hpp

Kod: Zaznacz cały


#ifndef _CRAWS_MAIN_HPP_
#define _CRAWS_MAIN_HPP_

#include "server_socket.hpp"
#include "client_socket.hpp"

#endif

//eof



server_socket.cpp

Kod: Zaznacz cały

#include "server_socket.hpp"

ServerSock::ServerSock()
{
    struct sockaddr_in serwer =
    {
        .sin_family = AF_INET,
        .sin_port = htons( SERWER_PORT )
    };

    if( inet_pton( AF_INET, SERWER_IP, & serwer.sin_addr ) <= 0 )
    {
        std::cout << "err:server_socket:1:socket create" << std::endl;
    }

    sock = socket( AF_INET, SOCK_STREAM, 0 );

    int opt = 1;
    setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, & opt, sizeof( opt ) );

    if( sock < 0 )
    {
        std::cout << "err:server_socket:2:socket create" << std::endl;
    }

    if( fcntl( sock, F_SETFL, O_NONBLOCK ) < 0 )
    {
        std::cout << "err:server_socket:3:socket create" << std::endl;
    }

    len = sizeof( serwer );

    if( bind( sock,( struct sockaddr * ) & serwer, len ) < 0 )
    {
        std::cout << "err:server_socket:4:socket create" << std::endl;
    }

    if( listen( sock, MAX_CONNECTION ) < 0 )
    {
        std::cout << "err:server_socket:5:socket create" << std::endl;
    }
}

ServerSock::~ServerSock()
{
    shutdown( sock, SHUT_RDWR );
}

//eof


server_socket.hpp

Kod: Zaznacz cały

#ifndef _CRAWS_SERVER_SOCKET_HPP_
#define _CRAWS_SERVER_SOCKET_HPP_

#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/fcntl.h>

#include <iostream>

#define MAX_MSG_LEN 4096
#define SERWER_PORT 8888
#define SERWER_IP "127.0.0.1"
#define MAX_CONNECTION 10

class ServerSock
{
    public:

        ServerSock();
        ~ServerSock();

        int sock; // Gniazdo
        socklen_t len;

};

#endif

//eof



client_socket.cpp

Kod: Zaznacz cały

#include "client_socket.hpp"

ClientSock::ClientSock(const int &new_sock)
{
    std::thread t([&new_sock]()
    {
        while(true)
        {
            char buffer[ MAX_MSG_LEN ] = { };

            if( recv( new_sock, buffer, sizeof( buffer ), 0 ) <= 0 )
            {
                perror( "recv() ERROR" );
                exit( 5 );
            }

            printf( "|Message from client|: %s \n", buffer );

            strcpy( buffer, "Message from server" );

            if( send( new_sock, buffer, strlen( buffer ), 0 ) <= 0 )
            {
                perror( "send() ERROR" );
                exit( 6 );
            }

            //shutdown( clientSocket, SHUT_RDWR );
        }
    });

    t.detach();
}

ClientSock::~ClientSock()
{

}

//eof


client_socket.hpp

Kod: Zaznacz cały

#ifndef _CRAWS_CLIENT_SOCKET_HPP_
#define _CRAWS_CLIENT_SOCKET_HPP_

#include <cstring>

#include <sys/socket.h>

#include <chrono>
#include <thread>

#define MAX_MSG_LEN 4096
#define SERWER_PORT 8888
#define SERWER_IP "127.0.0.1"
#define MAX_CONNECTION 10

class ClientSock
{
    public:
    ClientSock(const int &new_sock);
    ~ClientSock();


};

#endif

//eof


Awatar użytkownika
edwardkraweznik
Posty: 3
Rejestracja: wtorek 20 kwie 2021, 07:27

Re: Wielowątkowy socket pod linuxem c++ 11 std::thread

Postautor: edwardkraweznik » niedziela 25 kwie 2021, 22:20

Poniżej wersja poprawiona, działa stabilnie i wydajnie.
Może posłużyć jako szkielet dla naszej aplikacji server.

Podstawowe informacje:
Działa w trybie nieblokującym, wielowątkowo.
Przy programowaniu zastosowano OOP, c++ 11, std::thread

https://cyfronika.craws.pl/download/linux_socket.7z


Wróć do „Pisanie programów w C++”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 2 gości