Для своего проекта мне нужно реализовать передачу данных по протоколу TCP. Моих знаний и опыта хватило для примитивного сервера на Python:
- Программа работает, выполняет одну задача за другой
- В какой-то момент послылает запрос и приостанавливает свою работу, пока не получит ответ
- Получает ответ и продолжает свою работу Но это очень неэффективно, особенно когда нужно передавать очень тяжёлые файлы по несколько гигабайт:
- Программа условно разделяет файл на небольшие чанки.
- Посылает запрос с чанком файла, а следующий чанк отправит только после получения ответа о текущем
Максимальная скорость передачи, которую мне удалось достичь - 4 мегабайта в секунду в локальной сети. Было бы гораздо эффективнее просто закидать сервер тысячами пакетов, и собирать ответы от сервера в буфер, в который периодически можно поглядывать, чтобы потом докинуть неудачные пакеты.
И в этом заключается странность ситуации. Мне не хватает текущих знаний - в колледже об этом вообще ничего не говорили, но я представляю работу с сетью себе примерно так:
- Программа создаёт сокет
- Настраивает сокет
- Биндит сокет на порт
- Когда приходит запрос или ответ на запрос - операционная система записывает данные в некий «буфер входящих пакетов»
- Программа читает часть «буфера входящих пакетов»
И если это действительно так - то я хочу добиться асинхронности за счёт «««редкого считывания»»» буфера. То есть программа будет делать другие дела помимо ожидания ответа, например - работа с интерфейсом (а то программа, которая пошлёт пакет и будет рисовать интерфейс одновременно - тупо зависнет, а параллельность не везде возможна), или послать ещё запрос, а потом ещё и ещё, хотя ответ на первый запрос ещё не пришёл.
Да, в Python существуют библиотеки для асинхронной работы, но асинхронность в высоких языках я воспринимаю как мега-ужасный костыль - она быстро превращает проект в мега-сложную и сверх-запутанную структуру с огромным количеством абстракций и систем защиты от «гонок». Любой проект превращается из простого «сделать это а потом то» в «держать абстрактный класс с содержанием других классов, наследующих от других классов другие классы», и для моего не самого гениального мозга это воспринимается как мусор, в котором абстрактность на абстрактности, и абстрактность абстрактностью погоняет.
Мне кажется, что асинхронность на более низком уровне - это очень простая вещь, например просто «««редкое считывание»»» буфера. Никаких потоков, «гонок», семафоров и IPC. Просто буфер, который иногда можно читать. И вообще, я воспринимаю асинхронность на низком уровне как просто очень грамотно спроектированную программу, которая эффективно тратит время - на работу, а не на пустое ожидание.
Почему не хочу использовать многопоточность?
- Мой проект должен работать на любом тостере, на любом самоваре, а значит - многопоточности может и не оказаться.
- Я считаю многопоточность огромным усложнением проекта - в нём сразу возникнет куча проблем с «гонками», семафорами и безопасностью.
- Многопоточность ускорит работу сети в 2-24 раза, а грамотная асинхронность - в сотни тысяч раз, если не в миллионы или миллиарды.
Почему не async из Python? Потому что это костыль е_аный, а не асинхронность.
Я хочу использовать HTTP, и пока не знаю, как мне подружить его с такой «буферной асинхронностью», если она будет реализована самостоятельно. Поэтому было бы неплохо достичь «адекватной с моей точки зрения» асинхронности в Python. Может, написать библиотеку, которая даёт доступ и функции для работы с «буфером входящих пакетов», может даже в виде простого Python списка. Нет, я не буду писать свой проект полностью на Си - боюсь, что каждый самостоятельно написанный парсер не будет учитывать миллионы давно открытых уязвимостей, и в итоге мой проект будет решетом. Тут я не против абстракций, когда дело касается безопасности.
Плохой новостью для меня окажется, если просто поглядывать в буфер раз в 1/4 секунды - не выйдет, по причинам типа:
- Accept переводит процесс в состояние «заблокировано», пока не будет установлено соединение
- Listen переводит процесс в состояние «заблокировано», пока не придёт новый пакет
И типа из-за этого программа не сможет заняться своими делами, такими как отрисовка интерфейса и отправка других, следующих пакетов. Было бы печально, если бы такое не получилось.
В общем и целом - помогите разобраться в самоучке.
Покидайте полезных статей с примерами, пожалуйста, я сейчас нахожу только воду и статьи, сгенерированные нейросетями, аля «чтобы добиться асинхронного TCP соединения на Python…» и дальше какой-то абстрактный код, который потом превращается в Java, а затем в рецепт салата Цезарь из резиновых покрышек.
Ну или просто помогите разобраться, как эта работа с сетью работает на низком уровне. Я верно мыслю о «грамотной асинхронности» через «редкое считывание» некого «буфера входящих соединений», или же я неправильно предположила, и такое невозможно, и всё это лишь глупая мечта наивной сишницы?
Хочу добиться своего на Си или Python.
Спасибо заранее ^~^