Как реализовать мультипроцессорный сервер с SO_REUSEPORT и epoll

Рейтинг: 2Ответов: 1Опубликовано: 09.03.2023

Написал простой веб-сервер на чистом си на Linux Ubuntu, который использует epoll: один процесс, один поток, дескриптор просыпается -> читаем данные и так по кругу. В общем, хотелось бы сделать это на нескольких ядрах, процессах. Сначала я думал делать через одну очередь (listener), который отдает воркерам соединения. Потом прочитал про SO_REUSEPORT, точнее, наткнулся на эту статью: https://habr.com/ru/post/259403/

Примеров нет, статья на медиум непонятная (для меня). Как это должно выглядеть кодом? Пока есть что-то такое, может, работает так:

#include <sys/socket.h>
#include <netinet/in.h>
#include <strings.h>
#include <unistd.h>

void create_worker() {
    Создаем сокет новому воркеру
    Биндим его на тот же адрес
    Запускаем epoll
}

int main() {
    int master_fd = socket(AF_INET, SOCK_STREAM, 0);

    const int enable = 1;
    setsockopt(master_fd, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(enable));

    struct sockaddr_in master_addr;
    bzero(&master_addr, sizeof(master_addr));
    master_addr.sin_family = AF_INET;
    master_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    master_addr.sin_port = htons(8000);
    bind(master_fd, (struct sockaddr*)&master_addr, sizeof(master_addr));

    // Создаем 3 воркера, просто для теста
    for (int i = 0; i < 3; ++i) {
        create_worker();
    }

    for (;;) {
        Как передавать соединения воркерам?
    }

}

Не понимаю, как сделать именно такую логику - это нужно для каждого нового процесса создавать ему сокет, или очередь, или не нужно создавать очередь и сокет, тогда как отдавать им соединения? Не создавать потоки, это понятно как делается, а один процесс=один поток, который крутится в цикле, и так для каждого воркера. Читал более-менее книгу "Unix. Сетевое программирование", там примеры, касающиеся конкретно этой темы мне непонятны (про SO_REUSEPORT там нет). Пожалуйста, опишите подробно, если не составит труда. Готовый код не нужен, просто логику, куда что должно передаваться, как функционировать

Ответы

▲ 0

Передай дескриптор на сокет воркерам и делай accept внутри воркера.

reuse_port вроде даже не нужен при этом. Он для передачи сокета в другую программу. Могу ошибаться - когда занимался этим быстро перешёл на libuv.