Как сделать многопоток сокетов?

Здравствуйте, хочу сделать сервис для сервера линукс, синхронизация файлов с сервером и всеми моими устройствами.

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

Сделал небольшой, самый простой чат на сокетах, чтобы понять как они работают в с++:
Серверная часть:
#include <iostream>
#include <string.h>
#include <cstdlib>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
 
#define ERROR_SERVER "SERVER ERROR: "
#define CLIENT_CLOSE_CONNECTION_SYMBOL '#'
#define DEFAULT_PORT 1612
#define BUFFER_SIZE 1024
 
bool is_client_connection_close(const char* msg);
 
using namespace std;
 
int main(int argc, char const* argv[]) {
    int client;
    int server;
 
    struct sockaddr_in server_address;
 
    client = socket(AF_INET, SOCK_STREAM, 0);
 
 
    if (client < 0) {
        std::cout << ERROR_SERVER << "CONNECT ESTABLISHING";
        exit(0);
    }
 
    std::cout << "SERVER: Socket created!\n";
 
    server_address.sin_port = htons(DEFAULT_PORT);
    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = htons(INADDR_ANY);
 
    int ret = bind(client, reinterpret_cast<struct sockaddr*>(&server_address), sizeof(server_address));
 
    if (ret < 0) {
        std::cout << ERROR_SERVER << "binding connection. Socket has already been been established.\n";
        return -1;
    }
 
    socklen_t size = sizeof(server_address);
 
 
    std::cout << "SERVER: " << "Listening clients...\n";
    listen(client, 1);
    server = accept(client, reinterpret_cast<struct sockaddr*>(&server_address), &size);
 
    if (server < 0) {
        std::cout << ERROR_SERVER << "Can't accepting client.\n";
    }
 
    char buffer[BUFFER_SIZE];
    bool is_exit = false;
 
 
    while (server > 0) {
        strcpy(buffer, "=>Server connected!\n");
        send(server, buffer, BUFFER_SIZE, 0);
        std::cout << "=> Connected to the client #1" << endl << "Enter" << CLIENT_CLOSE_CONNECTION_SYMBOL <<  " to end the connection\n\n";
 
        std::cout << "Client: ";
        recv(server, buffer, BUFFER_SIZE, 0);
 
        std::cout << buffer << endl;
 
        if (is_client_connection_close(buffer)) {
            is_exit = true;
        }
 
        while(!is_exit) {
            std::cout << "Server: ";
            std::cin.getline(buffer, BUFFER_SIZE);
            send(server, buffer, BUFFER_SIZE, 0);
            if (is_client_connection_close(buffer)) {
                break;
            }
 
            std::cout << "Client: ";
            recv(server, buffer, BUFFER_SIZE, 0);
            std::cout << buffer << endl;
            if (is_client_connection_close(buffer)) {
                break;
            }
        }
 
        std::cout << "\n GoodBye" << endl;
        is_exit = false;
        exit(1);
    }
    return 0;
}
 
bool is_client_connection_close(const char* msg) {
    for (int i = 0; i < strlen(msg); ++i) {
        if (msg[i] == CLIENT_CLOSE_CONNECTION_SYMBOL){
            return true;
        }
    }
    return false;
}


Собственно то всё работает, но вот я сейчас сделаю например, если я буду делать кросплатформенное приложение, то мне нужно будет сразу же запускать сокет на всех устройствах, а мой код только для одного потока. Как можно сделать многопоточный в данном случае чат, а в дальнейшем загрузку файлов, фото, видео на сервер?
Я делаю эту программу только для себя, так как мне не нравяться nextcloud и подобные. Помогите разобраться, пожалуйста!
  • Вопрос задан
  • 189 просмотров
Пригласить эксперта
Ответы на вопрос 1
@res2001
Developer, ex-admin
Почитать книжку "Многопоточное программирование на С++". Там не про сокеты в многопотоке, а просто про сам многопоток. Многопоточная обработка сокетов не сильно отличается от любого другого многопотока.

Самый простой вариант - отдельный поток на каждого клиента.
В одном потоке крутится accept, при получении нового клиентского дескриптора, запускаешь новый поток и передаешь ему дескриптор. Поток производит всю обработку запросов от клиента. При разрыве связи, поток завершается.
Достоинтсва: просто в реализации, минимум межпоточной синхронизации.
Недостатки: отдельный поток на дескриптор - это довольно дорого, но если не планируется обрабатывать соти клиентов одновременно, то вполне годный вариант.

Как альтернатива для случая не слишком большого количества клиентов - один поток + неблокирующие сокеты + асинхронная обработка.
Про работу сокетов в неблокирующем режиме можешь почитать: "UNIX: Разработка сетевых приложений" книжка старая, но актуальная. В магазине скорее всего не найдешь, но в интернете полно сканов.
Книжка хороша не только по неблокирующим сокетам, а в принципе как описание разработки сетевых приложений.

Отдельный вопрос - кросс-платформенное приложение. Книг на эту тему вроде не видел, но подходы имеются. Не то что бы это сложно, но есть своя специфика.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы