Нарисовал очередной
сниппет для работы с сокетами. Надо писать сервер для утилиты обслуживания ПЗС/КМОП матриц, а приличного сниппета у меня что-то под рукой не оказалось. Вот и решил написать.
Умеет локальные INET сокеты и UNIX-сокеты (в т.ч. безымянные - у которых первым символом идет нуль). Содержит простейший метод парсинга сообщений вида ключ[=значение], по одному сообщению на строку (разделение как обычно: '\n').
На сей раз с поддержкой неполных строк: если последняя строка сообщения не заканчивается '\n', она не выбрасывается, а к ней в следующий раз "дочитывается" новая порция данных.
Простой обработчик полей "ключ" принимает NULL-terminated массив структур
typedef struct{
mesghandler handler;
const char *key;
} handleritem;
Если поле "key" совпадает с ключом, вызывается handler. В него передаются fd, key и val:
typedef hresult (*mesghandler)(int fd, const char *key, const char *val);
fd - дескриптор сокета - нужен для возможности написать индивидуальное сообщение клиенту; key - на тот случай, если один обработчик будет несколько разных ключей обслуживать (скажем, сеттер целых чисел); val - значение, которое может быть и NULL, если ключ - простая команда.
Поллинг клиентов выполняю через poll(), так что нет нужды париться с синхронизацией потоков (как в случае, когда каждому клиенту один поток), да и меньше шансов, что ресурсов не хватит, если клиентов слишком много. Правда, все равно выделяется по буферу на клиента - чтобы сохранять останки предыдущих сообщений.
В моем случае максимальное количество клиентов - 30, так что буферы выделены статически. Но если их будет мегадофига, надежней будет аллокатором на каждого нового клиента буфер выделять, а после отключения - освобождать память. Правда, файловых дескрипторов может не хватить, но желающие иметь больше 4096 дескрипторов знают, что нужно делать.
Провел несколько проверок (в т.ч. заваливал мусором) - вроде не падает. Буду на следующей неделе добавлять в
CCD_Capture.