Перейти к содержимому

Лидеры


Популярный контент

Показан контент с высокой репутацией 08.10.2021 во всех областях

  1. 1 балл
    Посмотрел я на тему "Возрождаем OpenNet (не опять, а снова)" и ради интереса решил накодить свою реализацию. Так вот. Представляю NetQuartz. Что эта ерундовина может: Многоуровневые IP адреса. Можно хоть 1.2, хоть 26.89.1.2, хоть 734.84.1.97.73.4, все зависит от вложенности роутеров. Встроенный DNS. Простенький веб-сервер и браузер с поддержкой цветов. Простая регистрация устройства в сети (хочешь подключиться - поставил ПО на клиента, написал одну команду - все готово!) Что она пока не может: Нема API. Нема всяких <hr> <a href> и прочей фигни. Ну и браузер бы полностью гуишным сделать. Тестил только на проводных подключениях! В теории конечно и вайфай должен работать, но в теории. Что она не может и добавлять не планирую: Шифровка трафика и прочая ерунда с безопасностью Терминология: роутер == маршрутизатор Корневой роутер (сервер), корень [сети] - основой компьютер, связывающий маршрутизаторы и клиентов, выполняющий функции DNS сервера и лежащий в иерархии сети выше всех. Всегда имеет IP 0.0. В одной сети может быть только 1. Маршрутизатор, роутер - компьютер, обеспечивающий перенаправление пакетов (маршрутизацию) от отправителя к получателю. Пакет (в контексте данного проекта) - 4 текстовых поля - Отправитель, Получатель, Тип, Данные Клиент - Любой компьютер / планшет / микроконтроллер / дрон / робот, подключенный к сети, являющийся конечным узлом. (То бишь, не имеющий дочерних узлов.) Узел - любое устройство в сети. Как это все работает: В контексте данного раздела "послать" == modem.send(). Все работает на 1110 порту. Если пакет типа DATA или DNSANSWER (в последнем случае 3-ий шаг выполнятся не будет, т.к. пакет уже послан с корня сети.): Клиент-отправитель посылает пакет на роутер, который его зарегистрировал в сети. Роутер получает пакет. Теперь есть несколько вариантов обработки: 1. Получатель находится в подсети роутера (включая вложенные подсети): роутер находит MAC узла, находящегося в адресе получатеся сразу после IP данного роутера и посылает на него пакет. Здесь неважно, является ли этот узел роутером или уже клиентом. Если получит роутер - пункт 2 повторится. 2. Получатель находится вне подсети роутера: Здесь еще проще - роутер просто посылает этот пакет родительскому узлу. Корневой сервер получает пакет. Данный шаг будет проделан, только если во время 2-ого шага роутеры добросали пакет вверх прямо до корня (например, в случае если отправитель 1.2, а получатель 2.3). Тут происходит все то же самое как и в 2.1. Клиент-получатель принимает пакет. На этом путь пакета завершен. Как он будет обработан - определяет ПО. Если пакет типа DNSREG или DNSLOOKUP: Клиент-отправитель посылает пакет на роутер, который его зарегистрировал в сети. Роутер получает пакет и перенаправляет его на родительский узел. Так повторяется, пока пакет не достигнет корня. Корень получает пакет, обрабатывет его и посылает ответ в виде DNSANSWER пакета. Если пакет типа FINDPARENT: (эти действия происходят при вып. кмд qclient find. При исп. другого ПО алгоритм обработки пакетов на стороне клиента может отличаться.) Клиент-отправитель посылает пакет методом broadcast. В поле данные указано "find". Любой роутер, получивший это отзывается сообщением (не пакетом) "FINDROUTER:ME". В т.ч. и корень. Клиент получает самый первый пакет и отсылает обратно уже методом send пакет FINDPARENT. В поле данные уже указан MAC роутера, на котором клиент желает зарегистрироваться. Собственно на этот же MAC и отсылается пакет. Роутер, получивший пакет, сравнивает свой MAC с указанным, и если они совпадают, то выдает клиенту IP и отсылает клиенту сообщение (не пакет) с его IP. Клиент сохраняет все в qclient.conf в формате MACродителя;свойIP. Железо и ось: Требования по железу: Обязательная сетевая карта. Минимум 25КБ свободного дискового пространства. Видеокарта 1+ ур. Рекоменд. дисплей. Процессор мин 1+, рекоменд 2+. ОЗУ не тестил. На тестовых компах стояло 2*2уровень На всех тестовых компах стояла ОпенОСЬ из коробки без модификаций. Как этим безобразием пользоваться: Создаем корневой сервер: Качаем на него root.lua и ttf.lua в папку /home/. Создаем папку /home/QuarksRouter/. Запускаем root.lua Создаем роутеры: Качаем unit.lua и ttf.lua в папку /home/. Создаем папку /home/QuarksRouter/. Подключаем и запускаем роутеры: Качаем qclient.lua в папку /home/. Пишем qclient find. После запускаем unit.lua Подключаем клиентов: Качаем qclient.lua в папку /home/. Пишем qclient find. Настраиваем веб-сервер: Качаем server.lua, желательно в папку /home/QServer/. Там же создаем папку /home/QServer/mctpdocs/, в нее будем пихать странички. ОБРАТИТЕ ВНИМАНИЕ! Страницы без расширений. Домашняя - index. Делаем странички: Пихаем файлы без расширений в папку /home/QServer/mctpdocs/. В них пишем любой текст. Поддерживается цветовое форматирование как в обычном майне, с помощью &. Также можно менять фон. Для этого пользуемся теми же колоркодами, только с префиксом не &, а ^. Запускаем сервер server.lua Ставим браузер на клиента: Качаем web.lua. Пишем web <url>/<page> (web test.low/test) для доступа. Регистрируем домен: На веб-сервере пишем qclient -p -l --r="0.0" --d="DNSREG;тутжелаемыйдомен". Собственно все. Гайд по qclient: -p - обязательно писать -l - слушать входящий пакет --r="ip.получателя" --d="типпакета;данные" Гайд по пакетам: Формат пакета: IPотправителя;IPполучателя;тип;данные Возможные типы: DNSREG - регистрация домена. В поле ДАННЫЕ пишем желаемый домен DNSLOOKUP - поиск ip по домену. В поле ДАННЫЕ пишем желаемый домен. DATA - пакет с данными. Типы, которые юзать нежелательно: DNSANSWER - ответ корневого сервера. В поле ДАННЫЕ указано QDNS:ответ. FINDPARENT - единственный broadcast-пакет. Регистрация в сети. Ссылки: root.lua https://pastebin.com/BDBsU4qm unit.lua https://pastebin.com/drZQ4MD0 qclient.lua https://pastebin.com/wMZqWwwL ttf.lua https://pastebin.com/rhbG8CW8 server.lua https://pastebin.com/mjzSm4Hi web.lua https://pastebin.com/xNYssMWc P.s. это мой первый проект на луа.
  2. 1 балл
    О том и речь. Делимое-то тоже целочисленное. Всё целочисленное: и операция деления, и делимое, и делитель, и частное. Но есть нюанс. Для понимания сути происходящего пришлось погрузиться в чтение исходников Lua. Пересказывать всю цепочку поисков слишком долго. Поэтому кратко изложу принципы. Сначала ищем по всем файлам фрагмент "idiv", затем сопоставляем, что откуда вызывается, а для завершения картины запрашиваем построение ассемблерного листинга нужных файлов с использованием опций из makefile. В сухом остатке имеем: Есть две разные операции целочисленного деления: для целых и для дробных чисел, как бы странно это не звучало. Операция целочисленного деления реализована гораздо более сложным кодом, нежели деление дробных чисел. Целочисленное деление дробных чисел: # lobject.c:81: case LUA_OPIDIV: return luai_numidiv(L, v1, v2); vdivsd %xmm1, %xmm0, %xmm0 # v2, v1, tmp101 vroundsd $9, %xmm0, %xmm0, %xmm0 #, tmp101, <retval> ret Целочисленное деление целых чисел: # lobject.c:60: case LUA_OPIDIV: return luaV_idiv(L, v1, v2); movq %rcx, %rdx # v2, movq %rax, %rsi # v1, jmp luaV_idiv # ... luaV_idiv: leaq 1(%rdx), %rax movq %rdx, %rcx cmpq $1, %rax jbe .L350 movq %rsi, %rax cqto idivq %rcx xorq %rsi, %rcx js .L351 ret ... Часть кода вырезана, там обрабатываются проверки деления на ноль и работы с отрицательными числами. Но и в этом куске кода почти все операции выполняют эти самые проверки. Необходимыми же операциями являются лишь idivq, да ret. Возможно, там нужны ещё какие-то операции перемещения из регистра в регистр, но они быстрые в сравнении с названными выше. Влияют. Тем не менее я рискну предположить, что на чистом Си без вспомогательных проверок целочисленное деление выполнится быстрее нежели дробное. Даже с SSE-оптимизациями. Возможно, кто-то проверит.
  3. 1 балл
    Неожиданно Это небось всякие оптимизации под SSE влияют
  4. 1 балл
    Lua не перестаёт удивлять. $ lua5.3 -e 't0=os.clock()local v for i=1,1e9 do v=i//1.0 end print(os.clock()-t0)' 11.848781 $ lua5.3 -e 't0=os.clock()local v for i=1,1e9 do v=i//1 end print(os.clock()-t0)' 16.08497 Операция целочисленного деления на целочисленную константу работает медленнее, нежели на константу с плавающей точкой. Соответственно, округление (val+0.5)//1.0 также будет выполняться быстрее, чем (val+0.5)//1.
  5. 0 баллов
    Вопрос обсуждался здесь: https://github.com/IgorTimofeev/MineOS/issues/356 Если кратко - документации нет, и знания придется добывать самостоятельно
  6. 0 баллов
    В OC встроен TLS только для HTTPS-запросов. Если надо кастомный TCP-сокет, обёрнутый в TLS, то надо самому имплементить TLS-протокол. Без дата-карты 3 уровня будет сложно: придётся делать криптографические примитивы на Lua.
  7. 0 баллов
    Я так понимаю, что TLS присутствует только для запросов (https://)? Если да, то как можно передавать поток, чтобы он оставался защищенным без использования Data Card?
  8. 0 баллов
    Вообще, из наличия в статье пятого пункта уже следует, что с обёртками я знаком и в путешествии к докам не нуждаюсь. Поэтому буду считать, что этот комментарий не ко мне обращён. Тем не менее, обе функции бесполезны, кроме примитивных случаев. internet.request не ждёт соединения с сервером. Хотя она прокидывает ошибки через error, этого недостаточно. См. 3.2–3.4 про то, как правильно послать запрос и получить ответ. А с таким кодом смысла в использовании обёртки ноль. internet.open кладёт оригинальный сокет в приватные свойства. Заставляет программиста постоянно и без причины дёргать :read() и не даёт воспользоваться сигналом internet_ready. Поэтому не только бесполезен, но и вреден. Нужно вызывать internet.socket, чтобы можно было получить id сокета и вызвать finishConnect, и вручную класть стрим в буфер. См. 4.5–4.8 про то, как правильно создать и использовать сокет. Таким образом, действительно полезна только одна функция — internet.socket. И очень зря она не удостоилась такой характеризации цитируемым комментарием.
  9. 0 баллов
    Не читал комменты выше но вообще-то есть обертка для всего этого.Почитайте https://ocdoc.cil.li/api:internet.Полезные там только 2 функции и это internet.open() и internet.request().
  10. 0 баллов
    Этот пост, я ещё раз повторюсь, не столько про интернет-карточку, сколько про обработку ошибок. Даже assert поставить — это уже обработка ошибок. local handle = assert(request(url, nil, nil, 5)) В коде из цитаты обработки ошибок нет. Ошибка если и есть, то теряется. Такой код проблему не решает и ещё порождает новые. Поэтому код неправильный. Меня огорчает, что код скопирован, а времени то, чтобы понять, как он работает, не потрачено совершенно. Внутри функции request находится цикл. Этот цикл ждёт соединения с сервером. timeout ограничивает время пребывания в этом цикле. Сколько ставить — это не мне решать, поэтому именно он и параметром к функции выведен. Зависит от программы. Сетевые приложения никогда не были простыми. Исключительных случаев огромное множество, и за всеми надо уследить. В посте я постарался объяснить, зачем я использую свою обёртку и что именно она делает. Я не могу дать полностью готовый кусок кода и сказать, что это канон. Самое универсальное — это функция request. Как использовать, зависит от приложения. Здесь я нарисовал с assert пример — при любой ошибке программа будет крашиться. Удобно при разработке. Если есть консольный интерфейс, надо ошибку обрабатывать явно. Например: local handle, err for i = 0, math.huge, 1 do handle, err = request(url, nil, nil, 5) if handle then break end local delay = math.min(180, i ^ 3) io.stderr:write([[ We've had a problem fetching a webpage: %s. Retrying in %d seconds...]]):format(err, delay)) os.sleep(delay) end В посте как раз консольная программка, к слову. Если интерфейс графический, ошибку писать надо куда-то ещё. Если программка автономная, то ошибку куда-то в лог класть.
  11. 0 баллов
    Не понял, как мне использовать request из примера, просто по ссылке мне нужно получать JSON ответ я добавив ваш код, выполняю local stat = request("https://levshx.000webhostapp.com/loader.php?option=stat", nil,nil,5) if stat then ... но stat = nil и каким образом подбирать timeout пожалуйста, можно получить пример использавання ?
  12. 0 баллов
    Эх, вот бы сюда сочный protected для подклассов... И костыляешь что хочешь, и либа целёхонькая
  13. 0 баллов
    А-а-а. Вспомнил Python полгода назад, а там приватные поля как раз через __ оформляются. Теперь вот и в Lua так делаю. С одной стороны, если юзер смотрит, какие поля есть (в интерпретаторе Lua в OpenOS есть автодополнение по полям таблицы), он сразу видит, что это что-то внутреннее, что может сломаться при обновлении либы, даже не смотря в доки. С другой стороны, если ему надо что-то закостылять, чего автор либы не предусмотрел, есть где развернуться.
  14. 0 баллов
    Я не про do ... end, а про __. Дело привычки, видимо. Крайне сложно принять факт наличия публичных полей, которые "эстетически" помечены приватными в ООП-системе. Я бы их тогда в сам объект вовсе не вносил, оставляя реализацию в виде локальных функций в начале скрипта. Впрочем, либа твоя, хозяин-барин, мяу
  15. 0 баллов
    И ведь действительно. Самое простое упустил. ¯\_(ツ)_/¯ Не, do .. end — это исключительно для структурирования кода конструкция. А setmetatable заменяет цикл. Приватными вещи в луа делать смысла большого не вижу, если только не требуется это задачей (например, публичный луа-терминал делать). Достаточно пометить внутренние функции через __.
  16. 0 баллов
    А, понятно, это имеет смысл. Переписывать никто не требует, олдфаги всё поймут, а нубасы пусть курят основы хв Ну почему же? Возьмем элементарный код: local function meow(self) print(self.abc) end local function newObject() return { abc = 123, meow = meow } end local function meowOverriden(self) if self.condition then meow(self) else print("Not condition") end end local function newObjectExtended() local self = newObject() self.condition = true self.meow = meowOverriden return self end Объекты? Есть. Наследование? Есть. Переопределение методов? Есть. Метатаблицы? Да на фиг не нужны. Этот код - такая же отсебятина и дело уже моей привычки. Я хотел обратить внимание не на метод реализации ООП (ибо все пишут как привыкли), а на его избыточную сложность для гайда: если уж делаешь библиотеку, использующую "железный занавес" для приватных членов через метатаблицы, то, как мне кажется, они должны быть полностью приватны для отдельно взятого класса. Чтобы, к примеру, нельзя было творить вот такую грязь: local client = stem.newClient(...) client.__opcodes[0] = "hehe" client.__craftPacket(...) Это же в корне ломает концепцию приватности, позволяя потрошить либу как душе угодно. Пофиг ли на это? Конечно пофиг. Но зачем тогда усложнять изящную либу и делать приватные члены? А если усложняешь, то почему не используешь полное экранирование с внутренним использованием rawget?
  17. 0 баллов
    Критика валидная. Да, это так, не отрицаю. Четвёртый пункт не для новичков. Если бы я писал для новичков, сначала бы пришлось описывать, что такое сокет, что значат 3 буквы TCP, чем request не устраивает. Эта часть предназначена целиком для тех, кто уже пользовался сокетами (не обязательно на Lua). В целом, вся запись подразумевает, что читатель уже знает Lua и использовал интернет-плату прежде. Наверное, надо было об этом написать явно. В чужой программе у меня возникли бы те же сомнения. "А чем процедурный стиль не угодил?" — этот вопрос задал бы в первую очередь. Получилось это так. Изначально я писал библиотеку, а не приложение. Написав 80% текста, я затем передумал и решил превратить библиотеку в чат-клиент. Но переписывать весь код было жалко, поэтому выбросил лишь отдельные части. Если бы начинал сразу приложением оформлять, разумеется, ООП был бы бесполезным, так как настройки бы все я запёк в константах в начале программы. Но мне было лень. Добавил для этого пункт 4.1, переписал 4.2, вставил в остальные пункты контекст и решил, что и так сойдёт. Не знаю, стоит ли сейчас переписывать без объектов. В коде только self исчезнет. Гм. Я до этого комментария считал наоборот. Где бы ни рассказывали здесь про то, как делать ООП, шаблон один и тот же: функция-конструктор new, метатаблица в некотором виде (где-то с рекурсивной ссылкой в __index, где-то таблица методов и {__index = methods} в конструкторе). do ... end — моя отсебятина, но выполняет она исключительно декоративную функцию. А какие ещё способы используются? На ум приходят только замыкания, но это уже какой-то костыль экзотический. P. S. Вообще, приятно, что кто-то потратил время, чтобы дельно покритиковать. :3
  18. 0 баллов
    Гайд по самой плате более чем достойный, однако начиная с пункта 4 он будет полностью понятен лишь человеку, уже знакомому с луа/опенкомпами и работавшему с платой. Новичков отпугнёт. Поясню претензию: Во-первых, какое, блин, ООП? В чтении/записи в сокет функционала кот наплакал, и реализовать его процедурным подходом можно в разы проще и доступнее для понимания. Ты гайд пишешь или состязаешься с читателем? Со стороны это выглядит так: а давайте-ка, детишки, напишем объектную систему для мульти-соединений с сервером по всем канонам. А потом... будем использовать лишь ОДНО во фронтенде! *ba dum tss* Во-вторых, "привычно" для кого, для Fingercomp'а? В луа не имеется общепринятых конвенций по реализации объектов. Метатаблицы и приватные члены - это, безусловно, интересный подход, однако тут я бы задал себе несколько вопросов в порядке убывания приоритетности: Будет ли он быстрее работать и расходовать меньше ресурсов? Нужен ли он для клиента, использующего только 1 соединение с сервером? Будет ли он проще в реализации? Будет ли он понятнее в виде гайда для людей, впервые работающих с интернет-платой и луа в целом? Имхо, ответом на каждый из них будет "нет". Вытекающий вопрос "зачем, господи?" висит мёртвым грузом...
  19. 0 баллов
    Да, проверка "content-length" - обязательная штука с плохим интернетом. Я везде ее пихаю, иначе как в опеноси, приходится запускать скачивание несколько раз, а если загрузка происходит прямо из биоса, тогда может произойти котострофа.
  20. 0 баллов
Эта таблица лидеров рассчитана в Москва/GMT+03:00
×
×
  • Создать...