Компактная и портабельная программа, четко выполняющая свое предназначение — редкая для современного мира красота и услада для глаз опытного разработчика.
Именно такие проекты, реализующие различные серверы и клиенты для веба вы найдете в этой статье.

Ода миниатюризации
Есть много причин, по которым миниатюрные девушк.. ээ реализации программ заслуживают внимания:
обучение — врядли получится разобраться как устроен вебсервер, перелопачивая исходники монстров вроде Apache или Nginx, спасет только миниатюрная реализация;
основа для собственных проектов — большой объем чужого исходного кода под капотом вашего проекта будет висеть гирей и отвлекать ресурсы на поддержку, в отличие от чего-то маленького и простого;
борьба с энтропией — популярные библиотеки постоянно растут и раздуваются, при этом объем используемого функционала не особо меняется. Таким образом, большая часть кода в современном проекте с кучей внешних библиотек не используется никогда.
Разумеется есть определенные риски использования таких «наколенных» библиотек, связанные с неполной реализацией, безопасностью, работой под нагрузкой и так далее.
Но говоря откровенно, всего этого ныне хватает с головой и в больших популярных реализациях.
Еще с опытом приходит понимание, что любая программа — не более чем инструмент а реальную опасность, как и сто лет назад, представляют живые люди, не машины.
Тестовое окружение
Не стал опять заморачиваться с BSD, чтобы в третий раз не описывать специальную прослойку epoll-shim, позволяющую быстро и более-менее безболезненно портировать серверный софт с линукса.
На этот раз в качестве тестового окружения выступает обычная Ubuntu Linux 25.10, хотя и с немного нестандартным ядром.
Компилятором выступит штатный GCC:
gcc version 15.2.0 (Ubuntu 15.2.0-4ubuntu4)
Поехали смотреть интересное!
Sandbird
https://github.com/rxi/sandbird
Начнем погружение с весьма практичного проекта:
A tiny (~800sloc) embeddable HTTP server written in C89, compatible with Linux, OSX and Windows.
800 строк на чистом С, причем наиболее портабельного стандарта С89, c поддержкой Windows, Linux и MacOS — отличный набор для реального применения, например в качестве встроенного вебсервера.
Например в каком-нибудь устройстве.
Один из примеров, демонстрирующих работу этой библиотеки — на заглавном скриншоте к статье, причем показана обработка формы.
Вот так выглядит сборка примера:
cd example gcc hello.c ../src/*.c -I../src -std=c89 -pedantic -Wall -Wextra -o hello
Так выглядит код тестового приложения с использованием этой библиотеки:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include "sandbird.h" static int event_handler(sb_Event *e) { if (e->type == SB_EV_REQUEST) { printf("%s - %s %s\n", e->address, e->method, e->path); sb_send_status(e->stream, 200, "OK"); sb_send_header(e->stream, "Content-Type", "text/plain"); sb_writef(e->stream, "Hello world"); } return SB_RES_OK; } int main(void) { sb_Options opt; sb_Server *server; memset(&opt, 0, sizeof(opt)); opt.port = "8000"; opt.handler = event_handler; server = sb_new_server(&opt); if (!server) { fprintf(stderr, "failed to initialize server\n"); exit(EXIT_FAILURE); } printf("Server running at http://localhost:%s\n", opt.port); for (;;) { sb_poll_server(server, 1000); } sb_close_server(server); return EXIT_SUCCESS; }
Важный нюанс:
сервер не использует многопоточность, все клиентские обработчики работают в одном потоке.
зато с неблокирующими сокетами:
.. static void set_socket_non_blocking(sb_Socket sockfd) { #ifdef _WIN32 u_long mode = 1; ioctlsocket(sockfd, FIONBIO, &mode); #else int flags = fcntl(sockfd, F_GETFL); fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); #endif } ..
webs
https://github.com/nicholascok/webs
Следующий интересный и даже в чем-то уникальный проект, с лаконичным описанием:
a simple websocket server library.
Реализует с помощью ~700 строк на С89.. серверные вебсокеты!
Вебсокеты это чаты, это «live-streaming», это например отображение логов в реальном времени и тому подобные динамические штуки.
Так это выглядит в действии:

Так выглядит сборка тестового приложения:
gcc -c *.c examples/test.c -Wall -Wextra -Wpedantic -Wno-overlength-strings -std=c89 gcc -o webs *.o -lpthread
Как нетрудно догадаться по -lpthread, тут уже используется многопоточность на базе POSIX threads:
.. static void* __webs_main(void* _srv) { webs_server* srv = (webs_server*) _srv; webs_client* user_ptr; webs_client user; for (;;) { user.fd = __webs_accept_connection(srv->soc, &user); user.srv = srv; if (user.fd >= 0) { user_ptr = __webs_add_client(srv, user); pthread_create(&user_ptr->thread, 0, __webs_client_main, user_ptr); } } return NULL; } ..
К сожалению этот интересный проект по большей части прототип, иллюстрирующий как можно на коленке без внешних библиотек реализовать серверную сторону вебсокетов на чистом С.
В случае реального использования, столь вольное использование malloc для обработки входящих пакетов быстро превратится в проблему:
.. /* deal with normal frames (non-fragmented) */ if (WEBSFR_GET_OPCODE(frm.info) != 0x0) { /* read data */ if (data) free(data); data = malloc(frm.length + 1); ..
Так выглядит сокращенная версия тестового сервера вебсокетов, c минимумом обработчиков:
#include "../webs.h" int myFuncZ(webs_client* self) { printf("server %ld: (id %ld) connected!\n", self->srv->id, self->id); webs_send(self, "greetings, salutations!"); return 0; } int myFunc2(webs_client* self) { printf("server %ld: (id %ld) disconnected!\n", self->srv->id, self->id); return 0; } int main(void) { webs_server* server1 = webs_start(7754); if (!server1) { printf("failed to initialise a server.\n"); return 1; } server1->events.on_open = myFuncZ; server1->events.on_close = myFunc2; webs_hold(server1); webs_close(server1); return 0; }
Как видно из кода выше, все интересное происходит именно в обработчиках, где собственно и будет находиться ваша собственная логика, если вдруг решитесь использовать эту штуку.
Повторюсь, что весь этот проект, несмотря на всю свою интересность — сырой прототип и тащить в прод подобный код без переработки, "as-is" точно не стоит.
Собирается только для Linux и только с помощью gcc.
Прототип как он есть.
cpp-httplib
https://github.com/yhirose/cpp-httplib
Это уже более зрелая библиотека:
A C++ header-only HTTP/HTTPS server and client library
11к строк кода на C++11 и несколько зависимостей от внешних библиотек:
pthreads, brotli, OpenSSL, zlib
Реализуют весьма продвинутый HTTP/HTTPS сервер и клиент, причем фактически в одном файле. Есть поддержка сборки как на Linux так и Windows, причем для второй есть готовый проект для Visual Studio.
Разумеется это не мейнстрим и к качеству есть вопросы, зато все уместилось в очень небольшом коде, без особых ухищрений по миниатюризации и потому вполне читаемому.
Так выглядит сборка тестового сервера, использующего эту библиотеку:
g++ -o server -O2 -std=c++11 -I.. -Wall -Wextra -pthread \ server.cc -DCPPHTTPLIB_OPENSSL_SUPPORT -lssl -lcrypto \ -DCPPHTTPLIB_ZLIB_SUPPORT -lz -DCPPHTTPLIB_BROTLI_SUPPORT \ -lbrotlicommon -lbrotlienc -lbrotlidec
Н��сложно догадаться по флагам вроде CPPHTTPLIB_ZLIB_SUPPORT, что большая часть зависимостей отключаема.
Еще думаю, заблудиться в 11к строчках кода и одном единственном файле будет проблематично даже у
нейросетине самых опытных «плюсолюбов».
Так выглядит серверный «Hello, world!»:
#include <httplib.h> using namespace httplib; int main(void) { Server svr; svr.Get("/hi", [](const Request & /*req*/, Response &res) { res.set_content("Hello World!", "text/plain"); }); svr.listen("0.0.0.0", 8080); }
В лучших традициях Django или Rails, тут есть маршрутизация запросов и привязка к URL — в данном случае обработчик связывается с урлом /hi.
Вот так выглядит обработка загрузки файлов с помощью формы и POST-запроса:
#include <fstream> #include <httplib.h> #include <iostream> using namespace httplib; using namespace std; const char *html = R"( <form id="formElem"> <input type="file" name="image_file" accept="image/*"> <input type="file" name="text_file" accept="text/*"> <input type="submit"> </form> <script> formElem.onsubmit = async (e) => { e.preventDefault(); let res = await fetch('/post', { method: 'POST', body: new FormData(formElem) }); console.log(await res.text()); }; </script> )"; int main(void) { Server svr; svr.Get("/", [](const Request & /*req*/, Response &res) { res.set_content(html, "text/html"); }); svr.Post("/post", [](const Request &req, Response &res) { const auto &image_file = req.form.get_file("image_file"); const auto &text_file = req.form.get_file("text_file"); cout << "image file length: " << image_file.content.length() << endl << "image file name: " << image_file.filename << endl << "text file length: " << text_file.content.length() << endl << "text file name: " << text_file.filename << endl; { ofstream ofs(image_file.filename, ios::binary); ofs << image_file.content; } { ofstream ofs(text_file.filename); ofs << text_file.content; } res.set_content("done", "text/plain"); }); svr.listen("localhost", 1234); }
Так это выглядит в действии:

Разумеется подобный функционал — не откровение, особенно на 2026й год, но блин:
11к строк кода на всю красоту!
Теперь переходим к миниатюрным реализациям протокола FTP — для передачи файлов, если кто вдруг забыл.
tiny_ftpserver
https://github.com/adamwym/tiny_ftpserver
Вот такой «игрушечный» проект:
a tiny FTP server written in C++
Всего 1.5к строк на С++11 от безвестного китайского автора реализуют полнофункциональный FTP/FTPS‑сервер — с chroot, поддержкой локальных и анонимных юзеров и всем прочим.
FTPS это довольно редко встречающееся расширение протокола FTP, с поддержкой шифрования передачи данных. Не набравшее большой популярности ввиду появления SFTP и органичений самого FTP и потому мало известное широкой админской публике.
В работе:

Проект использует известную библиотеку libnet, о чем автор забыл сообщить и которую необходимо установить до сборки:
apt install libnet1-dev
Сама сборка происходит с помощью обычного cmake:
mkdir build && cd build cmake ..
Реализация FTP-сервера тут максимально классическая — используется chroot а использование 21 и 20 портов зашито в код:
.. int socketfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); struct sockaddr_in server_addr; memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_port = htons(21); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; ..
Все это означает, что запускать сервер придется от суперпользователя:
sudo ./tiny_ftpserver ../tiny_ftpserver.conf
У этого проекта есть один неожиданный нюанс:
на самом деле это.. студенческая работа.
И подобных проектов на Github оказалось великое множество.
Так что далеко не везде в 2026м году забыли что такое высшее техническое образование, что не может не радовать.
fineFTP Server
https://github.com/eclipse-ecal/fineftp-server
Следующий интересный и весьма редкий проект:
FineFTP is a minimal FTP server library for Windows and Unix flavors.
~2k строк на С++14 реализуют FTP-сервер в виде.. библиотеки!
В этом и есть основная фишка этого проекта — возможность встроить FTP (причем сервер а не клиент) в ваше собственное приложение.
Так выглядит код примера, с внедрением FTP-сервера:
#include <fineftp/server.h> #include <thread> int main() { // Create an FTP Server on port 2121. We use 2121 instead of the default port // 21, as your application would need root privileges to open port 21. fineftp::FtpServer ftp_server(2121); // Add the well known anonymous user. Clients can log in using username // "anonymous" or "ftp" with any password. The user will be able to access // your C:\ drive and upload, download, create or delete files. On Linux just // replace "C:\\" with any valid path. FineFTP is designed to be cross-platform. ftp_server.addUserAnonymous("C:\\", fineftp::Permission::All); // Start the FTP Server with a thread-pool size of 4. ftp_server.start(4); // Prevent the application from exiting immediately for (;;) std::this_thread::sleep_for(std::chrono::milliseconds(100)); return 0; }
Зачем и для чего такое может быть нужно — другой вопрос, все же обычно работу с файлами в конечном приложении (например обновление прошивки) стараются реализовать в виде клиента и через HTTP/HTTPS.
Но с точки зрения использования все отлично работает:

Это хорошая, взрослая библиотека, с несколькими коммитерами, с историей разработки, которая активно поддерживается и развивается.
Старого цирка с chroot и 21м портом тут нет, поэтому все работает без привилегий суперпользователя — на скриншоте выше как раз видно использование нестандартного порта для работы.
Поддерживается сборка для Linux, MacOS и Windows c приоритетом для последней.
Отличный проект, но далеко не последний в сегодняшней подборке.
rcpd
https://github.com/tenox7/rcpd
Этот проект — привет из далекого и славного прошлого:
This is a modern re-implementation of rcp (remote copy protocol) daemon, originally part berkeley r-commands.
Да, это самый настоящий сервер RCP, всего 300 строк на Golang от знаменитого в узких кругах компьютерных реконструкторов автора Tenox.
RCP это такой устаревший протокол передачи файлов между компьютерами с UNIX, уже мало пригодный для использования в современных реалиях ввиду отсутствия какого-либо шифрования и авторизации.
Крайне актуальный, если имеете дело с устаревшим оборудованием или встраиваемыми системами, которые до сих пор используют именно rcp для загрузки прошивок по сети.
Возвращаясь к проекту:
rcpd от Tenox реализует серверную сторону — сервер RCP
К которому подключаются клиенты для загрузки или скачивания файлов.
Так выглядит процесс копирования файла, в качестве клиента тут rcp из пакета GNU Inetutils:

Как видите и клиент и сервер запускаются от суперпользователя — такие были времена, RCP использует 514 порт, который нельзя занять без привилегий.
Сборка:
go build -o rcpd .
Кстати в Makefile проекта есть поддержка кроссплатформенных сборок, с весьма богатым выбором:

Стоит добавить, что протокол RCP сам по себе очень простой и не менялся весь период своего существования, что позволяет подключаться к этому RCP-серверу даже с помощью клиентских программ из 80х и 90х.
За кадром
Детально разобрать удалось лишь малую часть интересных находок, поэтому ниже буквально одной строкой про интересные миниатюрные, точно заслуживающие внимания.
url.c
https://github.com/cozis/url.c/
Парсер строк URL на чистом С и без зависимостей:
This is a small library to parse and manipulate URLs in conformance to RFC 3986 and (most of) the WHATWG specification.
Что умеет:
No allocations
No dependencies
The ability to switch between RFC 3986 and WHATWG with a flag
Relative reference parsing and resolution
URL normalization
Doesn't rely on null-terminated strings
LightFTP
https://github.com/hfiref0x/LightFTP
Еще один интересный проект миниатюрного FTP-сервера:
Small x86-32/x64 FTP Server
Поддерживается сборка под Linux/Windows/Mac, сам проект не мертвый и судя по коммитам — развивается.
uftpserver
https://github.com/cpopp/MicroFTPServer
Весьма специфичная реализация FTP-сервера для встраиваемых систем:
Minimal FTP Server that can run on an ESP8266 with MicroPython
Так я впервые узнал о существовании «микропетона» — давно существующего проекта, с огромным количеством поддерживаемого железа и широким функционалом.
Ну и в качестве финального аккорда:
https://github.com/mtheall/ftpd
FTP Server for 3DS/Switch/Linux.
Реализация FTP-сервера для.. Nintendo Switch!
Это такая игровая консоль для гиков если кто вдруг не в курсе:

P.S.
Оригинал как обычно в нашем блоге, пользуясь случаем приглашаю на свой доклад 7 февраля для Analyst Marathon, посвященный проектированию совершенного API:
