1. Java / Говнокод #14399

    +71

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    private byte[] readBytes(InputStream pInputStream, int pLength, int pRetryCounter) throws IOException, WhateverException
    {
        byte[] bytes = new byte[pLength];
        int bytesRead= pInputStream.read(bytes, 0,pLength);
    
        if (bytesRead == -1)
        {
            throw new WhateverException("End of InputStream has been reached");
        }
    
        if (pLength != bytesRead)
        {
            byte[] bytesReadNextAttempt = readBytes(pInputStream, pLength-bytesRead, pRetryCounter + 1);
            if (pLength != bytesRead + bytesReadNextAttempt.length)
            {
                // less bytes available; connection was closed
                throw new WhateverException( ... );
            }
            System.arraycopy(bytesReadNextAttempt, 0, bytes, bytesRead, bytesReadNextAttempt.length);
        }
        return bytes;
    }

    поддержка паршиал ресив. такого "метода" я еще не видел.

    ЗЫ а че в жабе нету никакого MSG_WAITALL?

    Запостил: Dummy00001, 22 Января 2014

    Комментарии (250) RSS

    • Не, чет я все равно не могу понять, как этой функцией пользоваться. Она же всегда заканчивается ошибкой и массив с байтами не возвращается :/
      Оно вообще работает, или я что-то пропустил?
      Ответить
      • ясно.
        Ответить
      • Читает данные в буфер. Если прочиталось сколько надо - ок. Если нет - вызывает себя для чтения остатка и копирует результат в хвост буфера.

        В теории это даже должно работать...
        Ответить
        • Ну это ок, если поток не закончится раньше буффера, а если закончится - то прочитаное непосильным трудом в топку?
          Ответить
          • > а если закончится - то прочитаное непосильным трудом в топку
            А очень часто так и надо. Транзакционная семантика: всё или ничего.

            Например, что я буду делать с половиной запроса? Тут проще выбросить его нахрен и ждать следующего.
            Ответить
            • Да не, не часто... а если там просто ХМЛ неопределенного формата читается - откуда читающему знать когда он закончится?
              Ответить
              • Content-Length?
                Ответить
                • во времена крестоложества мне было не западло и по голому tcp гонять xml-и.
                  а чтобы не ебаться с поиском поточного парсера, просто ждал терминирующего нуля в потоке - нулевой байт в xml не встретится
                  Ответить
                  • Как бы не всегда есть возможность получить поток с данными оформленными так как мне хочется. Как правило, как раз наоборот, данные оформлены как хочется поставшику, а не принимающей стороне.
                    Даже тот же гребаный спринговский MultipartFile или как он там называется - если нужно что-то менее тривиальное чем просто записать файл на диск, получим вышеуказаную проблему.
                    Ответить
                    • > спринговский MultipartFile
                      А getSize() у него разве нерабочий?
                      Ответить
                      • 1. Не факт, что он вернет то, что нужно.
                        2. Его вызывать - очень дорогое развлечение. Чтобы этот размер получить у ин-мемори стрима его целиком копируют в байтаррей (Это даже не Спринг, а Апачи это делает), и считает байты в массиве.

                        А что если клиетн - секретарша Люся, которой поручили залить на сервер 2 тыщи картинок к завтрашнему утру?

                        PS: http://grepcode.com/file/repo1.maven.org/maven2/commons-io/commons-io/1.3.2/org/apache/commons/io/output/ByteArrayOutputStream.java#ByteArrayOutp utStream.toByteArray%28%29
                        Ответить
                        • > 1. Не факт, что он вернет то, что нужно.
                          А в спринге разве не как в пыхе - сначала все аплоады сохраняется во временную папку, а потом уже срабатывает контроллер? Там что-то поумнее?
                          Ответить
                          • Нет, ин-мемори-стрим, никуда самостоятельно не сохраняется. Ну или я не дочитал маны.
                            Ответить
                            • О, и кстати, по поводу охуенно продвинутых технологий в виде ХТМЛ5: файлы посылаются то в ASCI (url-encoded). Поэтому нормальный флешевый загрузчик может сработать примерно на треть быстрее ХТМЛ аналога.
                              Ответить
                              • > url-encoded
                                О_о. Т.е. даже не base64? Куда катится этот мир...
                                Ответить
                              • что? зачем их посылают в ascii?
                                Ответить
                                • 3.2 Action on submit
                                  
                                     When the user completes the form, and selects the SUBMIT element, the
                                     browser should send the form data and the content of the selected
                                     files.  The encoding type application/x-www-form-urlencoded is
                                     inefficient for sending large quantities of binary data or text
                                     containing non-ASCII characters.  Thus, a new media type,
                                     multipart/form-data, is proposed as a way of efficiently sending the
                                     values associated with a filled-out form from client to server.

                                  http://www.ietf.org/rfc/rfc1867.txt
                                  Предложить-то предложили, вот только хер приняли. Может какие браузеры втихаря и организовали поддержку, но стандарт это не описывает (ну или может моя инфа устарела). По крайней мере всякие ж.квери плагины шлют урлэнкодед.
                                  Ответить
                                  • эм...
                                    как раз этот multipart/form-data и используется для засылки бинарных данных файлов

                                    и даже с помощью ajax это можно сделать
                                    http://www.w3.org/TR/2010/WD-XMLHttpRequest2-20100907/ раздел 4

                                    просто никто не виноват, что как всегда в ишаке это работает не раньше 10 версии

                                    и насколько я понимаю, есть ещё и http://dev.w3.org/2006/webapi/FileAPI/ просто он в хз насколько актуальном состоянии
                                    Ответить
                            • > Нет, ин-мемори-стрим, никуда самостоятельно не сохраняется.
                              Ну то ли я не те маны читаю...

                              The file contents are either stored in memory or temporarily on disk.

                              > Чтобы этот размер получить у ин-мемори стрима его целиком копируют в байтаррей (Это даже не Спринг, а Апачи это делает), и считает байты в массиве.
                              Можно увидеть именно эту строчку? А не преобразование BAOS в массив, которое я вижу по той ссылке. Или это просто догадки?

                              Мне все-таки кажется, что спринг писали не клинические идиоты, и размер BAOS (если он там юзается) они узнают через stream.size() а не через stream.toByteArray().length.
                              Ответить
                              • http://grepcode.com/file/repo1.maven.org/maven2/commons-fileupload/commons-fileupload/1.2.1/org/apache/commons/fileupload/disk/DiskFileItem.java#DiskFileItem.getSize%28%29


                                Не клинические их выписали, и попросили больше не возвращаться...
                                Ответить
                                • Мда. Это достойно отдельного говнокода.
                                  Ответить
                                  • Страница нормально не открывается, раскапитаньте.
                                    Ответить
                                    • > Страница нормально не открывается, раскапитаньте.
                                      return dfos.getData().length;
                                      Чтобы замерить длину буфера мы... берем длину буфера, выделяем byte[] подходящей длины, копируем в него все данные из исходного буфера (это была getData()), и... замеряем длину полученного byte[].

                                      И это все при том, что там в члене класса валяется та самая длина, и для ее получения достаточно было сделать dfos.getByteCount().
                                      Ответить
                • Так а если файл из файловой системы, сокета, и вообще Content-Length нужно доверять в последную очередь (а лучше вообще не доверять никогда).
                  Ответить
                  • ну так тебе надо определиться - шашечки или ехать
                    универсального решения не будет
                    поточные парсеры нужны, только когда они действительно нужны

                    во всех остальных (а это наверное 90%) прикладных случаях как раз проще всего отделить прием от проверки/обработки

                    если ты боишься DOS, то тебе и поточный парсер не поможет - я тебе легко нагенерю бесконечный валидный xml-документ, тут надо другой комплекс мер использовать
                    Ответить
                    • Нет, не DOS, Content-Length используют для того, чтобы обмануть кеширующий сервер и подставить в кеш левую страницу. Ну да это не важно, собственно. Важно то, что это присылает клиент, а он мог (и это будет более вероятным случаем), просто неправильно ее посчитать.
                      Эксплорер был долгое время известен тем, что не понимал этот параметр у гзипнутых страниц. У флеша с этим тоже проблемы были.
                      Ответить
                      • > обмануть кеширующий сервер
                        Нахрена сервер кеширует POST'ы?
                        Ответить
                        • Если это прокси - вполне оправданое поведение.
                          Но кто сказал, что это должен быть пост? Это не обязана быть загрузка файла, Content-Length может прийти с чем-угодно.
                          Ответить
                          • > Если это прокси - вполне оправданое поведение.
                            С каких пор кешировать POST'ы стало оправданным поведением?

                            Вроде даже RFC это запрещало...

                            > Content-Length может прийти с чем-угодно.
                            А кто будет его читать в чем-то кроме POST и PUT?
                            Ответить
                  • > Content-Length нужно доверять в последную очередь
                    Если Content-Length больше заданного в конфиге допустимого размера - шлём его нахуй. Если клиент прислал неправильный Content-Length (и мы нарвались на досрочный EOF во время загрузки данных) - шлём его нахуй. Вот и все дела ;) Нечего поважать рукожопых программистов, и так весь веб этим говном и костылями засрали...

                    В идеале вообще показать табличку "так и так, ваш браузер писали мудаки, пускай они и фиксят", жаль что так сделать обычно не дает начальство ;(
                    Ответить
              • > откуда читающему знать когда он закончится
                1) Длина отправлена заранее (аля content-length).
                2) chunked-encoding и его велосипедные аналоги.
                3) Логический конец, когда потоковый XML парсер сыт и доволен прочитав закрывающий тег.
                4) Какой-нибудь терминатор, как написал выше defecate++.

                В любом из этих случаев EOF посреди данных (т.е. пока не набралась нужная длина в пунктах 1,2, пока не встретился терминатор в 4, и пока не встретился закрывающий тег в 3) - однозначный фейл. И я бы его обрабатывал именно как ошибку.

                Функция, описанная в топике подойдет для вариантов 1 и 2.
                Ответить
        • Это же полная херня - использовать рекурсию там, где можно воткнуть цикл
          Ответить
    • "А я закачаю этот буфер с двух ридов."
      Ответить
    • >поддержка паршиал ресив.
      Чем не устроил readByte и ко? Оно даже исключения бросает.
      Ответить
      • бесполезная, некотролируемая рекурсия.

        и если (маловероятно) будут приходить данные по одному байту, то еще и копирования на O(n^2).
        Ответить
        • чо? про что это?
          Ответить
          • про строчку 19.

            если будет читаться побайтово N байт, то они будут скопированы (N*N)/2 байт.
            Ответить
            • Какое отношение это имеет к моему коменту?
              Ответить
              • сорри попутал с ГК. а ты о каком "readByte" говоришь?

                http://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html - здесь ничего не вижу.
                Ответить
                • Загугли. http://docs.oracle.com/javase/7/docs/api/java/io/DataInput.html
                  Ответить
                  • readFully тогда уж, а не readByte.

                    UPD: А ну хотя ты и написал "и ко". Все ок.
                    Ответить
                  • гуглил. ничего не находилось.

                    по виду интерфейс только файловыми причиндалами поддерживается. ГК то о сокетах - partial receive только же на сокетах может происходить.
                    Ответить
                    • > partial receive только же на сокетах может происходить
                      А также на пайпах, всяких там RS232 и прочих радостях...

                      > по виду интерфейс только файловыми причиндалами поддерживается.
                      Почему? Там вон судя по доке есть оберточка для любого InputStream'а, реализующая этот интерфейс - DataInputStream.
                      Ответить
                      • > А также на пайпах

                        wow. жаба с 1.4 наконец умеет пайпы! и ио мультиплексинг с недавних времен! не прошло и двадцити лет - и уже даже можно пытаться писать на этом что-то!! :)

                        > DataInputStream

                        не заметил. спасибо.
                        Ответить
                        • > J2SE 1.4 (February 6, 2002)
                          Уже 11 лет назад вышла ;)
                          Ответить
                        • > с недавних времен!
                          > пытаться писать на этом что-то!
                          Этим штукам в этом году как раз десять лет исполнится. Welcome to future.
                          Ответить
                          • Изменения такие мелкие, что других языках такие вещи появляются за год-2.
                            Ответить
                    • пщщ: java readByte ничего не находилось?
                      Ответить
                      • еще раз погуглил нормально: результат на четвертом месте.

                        щас прям погуглил в private mode: результат на первом месте.

                        гугля знает что я не жабщик. :)
                        Ответить
                        • Вспоминаю, как один пожаловался, что ему на одном сайте гей-рекламу показывают.
                          Ответить
                          • А по мне - если уж реклама показывается, так пускай уж таргетированная. Все-таки херня для серваков и вижуал студия больше радуют глаз, чем прокладки и туалетная бумага, как по телеку, или чем всякая неведомая хуита на помоечных хостингах файлов и картинок.
                            Ответить
                        • А вообще поставь адблок, разлогинься и будет тебе щастье.
                          Ответить
                          • это уже давно не работает. надо какой активный блок на куки и прочее ставить. я часто в хроме приватным режимом пользуюсь и замечаю что гугля даже там запоминает меня: следующие поиски зависят от предыдущих. пока не закроешь все приватные окна, состояние похоже не сбрасывается.
                            Ответить
    • Говорят, на винде нет MSG_WAITALL
      Ответить
      • [color=green]а зачем работать с сокетом неасинхронно?
        Ответить
        • Чтобы не было тредоблядства.
          А от блокировки избавиться просто: в винде можно повесить сообщения о приходе на какое-нибудь окно. Ну вот в функции этого-то окна и смотришь в сокет только когда надо. Короче, сия конструккция УМВР.
          Ответить
          • > окна
            Фублядь. Окно поднимать ради чтения из сокета.
            Ответить
            • Да пох, оно невидимое.
              Ответить
              • В виндах XP было невидимое окно, кажется, в консольном режиме, у залогиненного пользователя. Только запускалось оно с правами NT_AUTHORITY/SYSTEM. И с этим была связана какая-то уязвимость, уж не с переполнением ли буфера.
                Ответить
                • >окно
                  >запускалось оно с правами
                  Ответить
                  • Да, более корректно было бы выражение "сервис NetWork DDE DSDM, которому это окно принадлежало, запускался с правами", далее по тексту.
                    Ответить
            • Даже само название операционки как бы намекает на то, что всё будет делаться через жопу окна. Видимо у м$ не было тех, кто умел в абстаркции
              Ответить
              • Уже представил себе название операционки «Жопа XP» или «Жопа Vista». Последнее после перестановки слов у испанцев будет обозначать «Вид на жопу», а у латышей — «Жопа курицы».
                И логотип для такой ОС почти готов...
                Ответить
              • Да все там есть, асинхронный I/O даже получше будет, чем в линухе. Просто некоторые любят пожрать кактус.
                Ответить
                • в дельфи-7 на панели компонентов нет картинки IOCP
                  Ответить
                • "Да все там есть, асинхронный I/O даже получше будет, чем в линухе."

                  Да, лучше. Я на нем даже когда-то писал. Проблема только в том что под виндами мультиплексинг и асинк программирование сродни мазохизму, и мазохизму изощренных форм. Почему почти никто этим не страдает, а просто делают поток и делают все последовательно в этом потоке. Даже пару либ встречал которые типа "100% асинк" а на самом деле на каждый сокет садят по потоку и из потока этого потом дергают основное поток. Слегка дермовато, но работает как и ожидается.

                  На линухе это все настолько проще что даже не смешно. Я знавал только пару библиотек которые этим занимаются (libevent например), потому что мало кому эти библиотеки нужны - можно прекрасно и без них обходится. главный цикл вокруг poll() рисуется за 15-30 минут. libevent еще кучу всего другого может (асинк днс, плюс портабельный интерфейс) почему им еще и пользуются.
                  Ответить
                  • на что только не пойдут сишники, лишь бы не использовать буст
                    Ответить
                    • буст не предоставляет главного цикла. по крайней мере ничего такого не слышал/не видел.

                      QtCore (QCoreApplication) было более информативное замечание.
                      Ответить
                      • > буст не предоставляет главного цикла
                        boost::asio::io_service io_service;
                        io_service.run();
                        А это тогда что?
                        Ответить
                        • "А это тогда что?"

                          То про что я "не слышал/не видел".
                          Ответить
                      • что такое главный цикл? если он должен быть тесно связан с потоком, куда ось будет накидывать внешние события (сигналы), а ты, в свою очередь, будешь работать с гуём (потому что тебе, например, будет нельзя из другого потока это делать), то не предоставляет

                        если это просто сущность для удобства твоего как архитектора приложения - то он и не нужен
                        особенно в безгуёвых приложениях

                        я создаю, например, пул из 20 потоков, и мне всё равно, в котором из них будут исполняться логически более важные дела, а в котором - читаться из сети новости
                        Ответить
                        • "то он и не нужен. особенно в безгуёвых приложениях"

                          если ты делаешь асинхронные сокеты с мультиплексингом, то главный цикл нужен.

                          события они есть события - в независимости от гуёвости приложения.

                          и тем более если ты еще и многопоточность добавляешь: кто-то должен отвечать за (асинхронную) коммуникацию между потоками.
                          Ответить
                          • ну если ты только в этом смысле (управление всей кухней) - то главный цикл спрятан в недрах asio - как раз внутри io_service

                            особо вписаться туда ты не можешь (да и незачем)

                            и, как показывает практика, этих "главных циклов" тоже можно делать больше одного - числом примерно, сколько ядер в системе,
                            и затем асинхронные задачи (которые, понятное дело, не только сокеты - вообще всё приложение - это цепочка тысяч асинхронных задач) равномерно размазывать по этим ио-сервисам

                            и да, если говорить про сигналы (именно сигналы), то они все равно свалятся в основной поток приложения, а не в тред, где ворочается io_service

                            именно поэтому безгуевые приложения на асио в основном треде (в main) подготавливают и запускают всё что надо и потом вхолостую сидят ждут достойной кончины приложения (например, в бесконечном цикле с кондишен-переменной или просто со this_thread::sleep) - вот тут как раз место, где можно разгуляться для гуйни
                            Ответить
                  • > главный цикл вокруг poll() рисуется за 15-30 минут
                    Ну да. Я тоже такое делал на poll(). Больше всего времени ушло на поддержку таймеров.

                    Но сейчас, если я буду кодить что-то сишно-хардкорное и асинхронное, я лучше возьму тот же libev. Ленивый я стал :(
                    Ответить
                    • последний раз по приколу делал forking server. работает на ура.
                      Ответить
                      • Ну смотря какая задача. Для независимых форки рулят :) Правда потом затрахаешься портировать это под винду, если вдруг понадобится...

                        А для зависимых как-то влом париться с IPC, проще треды или асинхронку поюзать.
                        Ответить
                        • "Правда потом затрахаешься портировать это под винду, если вдруг понадобится..."

                          Все еще подмывает попробовать на это перле и посмотреть как будет под виндой работать. Потому что перл виндовый обещает что даже форк работает.
                          Ответить
                          • > даже форк работает
                            Работает или эффективно работает? :)
                            Ответить
                            • "эффективно работает" насколько я понимаю.

                              обещание видел в StrawberryPerl, а они поддерживают с WinXP а в XP еще никакого эмулятора форка вроде нет.

                              какие-то light weight processes в виндах вроде только с висты. деталей не знаю, но народ говорит что они позволяют сделать форк на виндах. (Chrome ими пользуется для под-процессов.)
                              Ответить
                              • В питухе насколько я знаю при форке используется copy on write, т.е. память у процессов общая, новая выделяется только при попытке изменения. На винде такого вроде нет, но зато нормальные треды.
                                Ответить
                                • > зато нормальные треды
                                  Чем линуховые pthreads ненормальны? Память общая, создаются быстрее процессов. Примитивы синхронизации в комплекте. Что еще надо то?
                                  Ответить
                                  • Почему тогда все так любят форк?
                                    Ответить
                                    • > Почему тогда все так любят форк?
                                      1) Исторически сложилось.
                                      2) Изоляция - можно часть форкнутых процессов запустить под другим юзером, и падение детей не влияет на родителя.
                                      3) В винде бы тоже иногда хотелось юзать создание процесса вместо тредов, да вот дороговато оно там, на порядок медленней, чем CreateThread.
                                      Ответить
                                      • >1) Исторически сложилось.
                                        То есть люди, которые думают о кроссплатформенности, юзают треды?

                                        >2) Изоляция - можно часть форкнутых процессов запустить под другим юзером, и падение детей не влияет на родителя.
                                        Это еще на кой хер?

                                        3) А еще оно создает 100500 процессов и хрен разберешься где чей. Ну разве что с процесс експлорером.
                                        Ответить
                                        • > То есть люди, которые думают о кроссплатформенности, юзают треды?
                                          Да.

                                          > Это еще на кой хер?
                                          Например, чтобы дети Индейца могли лезть только к своим хомякам, и никуда больше. На виндовом IIS тоже ведь пулы можно запускать под другим юзером, не замечал? Если это тебе не нужно - не думай, что это никому не нужно.

                                          > А еще оно создает 100500 процессов и хрен разберешься где чей.
                                          В линухе и треды когда-то показывались в ps как процессы ;)
                                          Ответить
                                        • >Это еще на кой хер?
                                          Изоляция процессов. Ваш КО.
                                          Если потомок решит сегфолтуться, то родитель не сходнет вместе с ним.
                                          Ну и плюс можно получить какие-нибудь ресурсы с правами рута, а потом дропнуться до nodoby:nogroup и послать хацкеров в далекое путешествие
                                          Ответить
                                          • >Если потомок решит сегфолтуться, то родитель не сходнет вместе с ним.
                                            Во-первых, поправьте если не прав, сегфолтится только один тред, но даже если не так - другие процессы даже под тем же юзером не сегфолтятся.
                                            Ответить
                                            • > поправьте
                                              если сегфолтится тред, то всё приложение умирает - если быть точным, сигнал засылается приложению, а не треду
                                              и в случае SIGSEGV у тебя не то, чтобы много вариантов выжить
                                              Ответить
                                            • > сегфолтится только один тред
                                              Да даже если и получится отловить сегфолт в одном треде, и убить его, не спасет это... Если тред засегфолтился - значит есть вероятность, что он где-то насрал в память, и продолжать работу - корейский рандом. А еще он мог проебать мутексы, оставить что-нибудь в промежуточном состоянии, или не закрыть какие-то файлы или сокеты...

                                              Так что лучший выход для проги - суицид без сохранения данных.

                                              > другие процессы даже под тем же юзером не сегфолтятся.
                                              Ну да.
                                              Ответить
                                          • >Ну и плюс можно получить какие-нибудь ресурсы с правами рута, а потом дропнуться до nodoby:nogroup и послать хацкеров в далекое путешествие
                                            Линуксбезопасность. Это как многозадачность в win 3.1 - все на доверии.
                                            Ответить
                                            • > Линуксбезопасность. Это как многозадачность в win 3.1 - все на доверии.
                                              Эм... может быть ты не так понял его фразу?

                                              Алгоритм примерно такой:
                                              - демон стартует под рутом
                                              - окрывает какой-то файл, который доступен только руту
                                              - и делает себе setuid на бесправного юзера
                                              - теперь он может юзать тот файл (пока не закроет его), но в остальном он бесправен

                                              Где здесь доверие, наоборот же ;)
                                              Ответить
                                              • Доверие, что демон дропнет права и не будет похекан до этого вместо того, чтобы сразу ему их порезать.
                                                Ответить
                                                • это тоже реализуемо, потому что можно написать хелпер, в котором открыть файл, дропнуть права и сделать exec демона которому не доверяешь (на коммандной строке или в окружении передавая номер дескриптора привилегированого файла).
                                                  Ответить
                                                • > чтобы сразу ему их порезать
                                                  Делать под каждого демона отдельную учетку? Ну и так тоже делают.
                                                  Ответить
                                                • >Доверие, что демон дропнет права и не будет похекан до этого вместо того
                                                  Демон начинает общаться с внешним миром только после сброса привелегий.
                                                  Ну а если нет доверия к самому демону(например, протрояненая проприетарщина), то можно последовать совету @Dummy00001 или юзать что-то вроде selinux. В последнем случае, получив рута, хакер ничего сможет только прочитать конфиги и забиндиться на определенный порт
                                                  Ответить
                                                  • > хакер ничего сможет только прочитать конфиги и забиндиться на определенный порт
                                                    СЕНСАЦИЯ! Взломавшие демона хакеры наткнулись на SELinux, который подстрелил их солью и заставил починить код чтения конфигов и обработки входящих соединений
                                                    Ответить
                                                  • >Ну а если нет доверия к самому демону(например, протрояненая проприетарщина),
                                                    Типа апинсорс не ломают. Адрес базы уязвимостей подсказать?
                                                    Ответить
                                                    • > Типа апинсорс не ломают

                                                      В любом случае, апинсорсной проге, скачанной из родного репозитория, подписанного gpg-ключём, я доверяю больше, чем проприетарной крякнутой проге, скачанной на просторах интернетов.
                                                      Ответить
                                    • потому что очень просто для программирования.

                                      вот тебе кусок из моего доморощеного форкающегося HTTP/0.1 сервака:

                                      my $ss = new IO::Socket::INET
                                              'LocalAddr' => $server_addr,
                                              'Type' => SOCK_STREAM,
                                              'Listen' => 128,
                                              'ReuseAddr' => 1;
                                      
                                      $ss || die "can't bind: $!";
                                      
                                      $SIG{CHLD} = 'IGNORE';
                                      
                                      while (1) {
                                              my $cs = $ss->accept();
                                      
                                              next unless $cs;
                                      
                                              my $child = fork();
                                              warn "can't fork child: $!" unless defined $child;
                                              if (!defined($child) || $child > 0) { undef $cs; next; };
                                      
                                              &serve_request( $cs );
                                              exit 0;
                                      }


                                      тоже самое на потоках будет в 2-4 раза длиннее. и например заботится о жизни сокета не надо: парент его закрывает после форка, в чайлде он закроется автоматом когда он завершится.
                                      Ответить
                                      • Лол треды не намного сложнее. Передаем треду замыкание, выход из функции - тред убивается.

                                        А вот в питоне такого конструктора с keyword аргументами почему-то нет.
                                        Ответить
                                  • Кстати да, с линуховыми птредами я попробовал распараллелить простую операцию, всё оказалось очень просто и понятно, а с виндовыми там небось не создашь тред без заполнения 100500 параметров, из которых три - это указатели на структуры с 100500 полями, из которых первое - это размер структуры, а второе - это какие поля являются важными
                                    Ответить
                                    • > а с виндовыми там небось не создашь тред без заполнения 100500 параметров
                                      Да почему, в винде тоже элементарно создается - пачка нуллов да указатель на функцию. Никакие структуры, емнип, заполнять не надо.
                                      Ответить
                                    • TarasB, пишешь на winapi? ССЗБ.
                                      Ответить
                            • к слову. "эффективно" они работают вроде бы как бы очень давно. я только что вспомнил про много-поточность в перле: оригинальная реализация делалась как раз для эмуляции форка на виндах. может оно так и сейчас осталось: форкнутый поток есть просто поток в котором все данные автоматом с оригинальным потоком шарятся (в отличии от обычных потоков где шарить нужно открыто).
                              Ответить
                              • >форкнутый поток есть просто поток в котором все данные автоматом с оригинальным потоком шарятся
                                Что такое автоматом шарятся? Общая память есть только у тредов.
                                Ответить
                                • да. стормозил. ничего не шарится.

                                  только что на 5.12 проверил - форк потоками эмулируется.
                                  (тест: perl -e "<>; fork; <>;")

                                  COW лень тестировать.
                                  Ответить
                        • Прыщепроблемы, форки вместо тредов. Кстати, чем вам, питухам, треды не угодили?
                          Ответить
                          • Для особо осведомлённых сообщаю, что "треды" в линупсе есть с версии 2.6, хоть и реализованы они через форк с полным сохранением мемори-маппинга родителя, а не с COW, как при обычном форке. Чем именно тебя не устраивает в таком подходе?

                            Ну и отдельные процессы хороши тем, что не грохают родителя в случае непредвиденных обстоятельств.
                            Ответить
                            • "Для особо осведомлённых ..."

                              ... в линухе с 2.6 нету больше fork()а - есть только clone().
                              Ответить
                              • > нету больше fork()

                                Щито за ересь? Куда он нахрен денется из unistd?

                                В 3.11 поглядел: sys_fork номер 2 sys_vfork номер 190.

                                То, что они релизованы через единую функцию внутри и это и так понятно.
                                Ответить
                            • >форк с полным сохранением мемори-маппинга родителя
                              Как это?

                              http://govnokod.ru/14399#comment212945
                              Ответить
                              • > Как это?
                                Ну при обычном fork'е включается COW маппинг, а при создании треда - тупо остается то же самое адресное пространство, без cow. Разве что стек новый заводится. Там и процессы и форки создаются через один syscall, емнип.
                                Ответить
                                • >форк с полным сохранением мемори-маппинга родителя
                                  Это форк, или это тред? Что это?
                                  Ответить
                                  • > Это форк, или это тред? Что это?
                                    С полным сохранением маппинга - тред.
                                    Ответить
                                  • > Это форк, или это тред? Что это?

                                    Вот оно, назамутнённое сознание юниксхейтеров.
                                    В юниксах есть только файлы и процессы, всё остальное лишь сон во сне
                                    Ответить
                                    • > всё остальное лишь сон во сне
                                      Еще сетевые устройства почему-то сбоку прикручены, в отдельном неймспейсе.
                                      Ответить
                                      • > в отдельном неймспейсе
                                        Мсье взялся за старое
                                        /sys/class/net - это отдельный неймспейс?
                                        Ответить
                                        • > /sys/class/net - это отдельный неймспейс?
                                          Дык это же только статистика и настройки устройства. В ifconfig или ip route я же немогу написать /sys/class/net/eth0.

                                          А само сетевое устройство отдельной нодой в /dev, емнип, не представлено.
                                          Ответить
                                          • Сетевое устройство представлено интерфейсом - вполне адекватный вариант.
                                            >В ifconfig или ip route я же немогу написать /sys/class/net/eth0.
                                            Зато можешь делать так
                                            echo 1440 > /sys/class/net/eth0/mtu
                                            Ответить
                                            • > Сетевое устройство представлено интерфейсом - вполне адекватный вариант.
                                              Я не говорю, что это плохо. Я говорю, что оно в другом неймспейсе.

                                              > Зато можешь делать так
                                              Ну я и с дисковыми устройствами много чего могу делать через sys, но они же имеют ноду в /dev, а сетевые - нет. А sys это просто удобный интерфейс для настроек.
                                              Ответить
                                    • Есть процессы, треды и что-то среднее?
                                      Ответить
                  • Просто на винде нормально работают треды. Проксипроверялки открывают 400 потоков без каких-либо проблем.

                    А подвисонами при днс запросе кстати страдают многие проги.
                    Ответить
                    • здесь я могу сказать с полной увереностью что на виндах потоки работают лучше.

                      потому что на виндах из-за багов реализации первых AIO в NT3.x/4.x мультиплексинг работал криво и единственный способ был это рас-поточивать. что мелкософт и съоптимизировал соответственно.

                      юнихи, даже когда потоки появились, еще долгие годы без аналога виндового critical section пытались что-то делать. на линухах красно-шапные идиоты еще и первый релиз futex'ов облажали. потоки заработали 100% надежно и без мелких граблей где-то только в 2005 - и только из-за давления со стороны server-side что бы жаба нормально работала.
                      Ответить
                • Кстати, а какая функция в винде устанавливает подписчика на события от сокета?
                  Ответить
                  • Да там овердохуя способов. И подписчика в большинстве из них прописать нельзя, только замутить свой цикл и самому разруливать события о готовности или завершении операций...

                    Для IOCP - CreateIoCompletionPort и его друзья.
                    Можно просто юзать ReadFile + OVERLAPPED с ивентом + WaitFor*.
                    Реактор можно собрать на WSASelect + ReadFile.

                    Могу и наврать, давно не работал с виндоблядскими API на таком низком уровне... Лучше всего, имхо, поюзать какую-нибудь либу в духе boost::asio, которая спрячет всю эту фигню поглубже под капот...
                    Ответить
                    • > И подписчика в большинстве из них прописать нельзя, только замутить свой цикл и самому разруливать события о готовности или завершении операций...

                      И чем невидимое окно-подписчик хуже?
                      Ответить
                      • в дельфях то? все отлично, продолжай
                        Ответить
                        • лол это был проект без VCL
                          только не надо говорить, что винапи в С++ и в Дельфи разное

                          так чем невидимое окно-подписчик хуже?
                          Ответить
                          • хуже чем что
                            чем пул потоков?
                            наверное, потому что оно 1) одно, будешь делать пул невидимых окон?, 2) кроме непосредственно треда, для которого ты его создал, ему наверняка приходится реагировать на кучу ненужной хуиты, 3) потребляет заведомо больше ресурсов, чем один поток, 4) капитальный отсос по кросс-платформенности

                            но т.к. это дельфишный проект, то это означает, что 1) какое же оно высоконагруженное, там наверняка единственный реактор на udp по самобытному протоколу, ради чего ты ещё решишь сделать асинхронность-то, 2,3) насрать на ресурсы и тормоза - всё равно будет меньше, чем у жабы/сисярпа, лишних 10кб никто не заметит, 4) ну дельфи же!

                            поэтому ещё раз: "в дельфях то? все отлично, продолжай"
                            Ответить
                            • 0) это не тредоблядство
                              нет, там tcp

                              какие ещё есть способы подписаться?
                              Ответить
                              • положа руку на сердце, использовать нативные виндозные библиотеки - IOCP там, или Timer Queues, или Registry, или ещё какая паршивая поебень - то ещё мучение

                                посмотри, что для дельфей-7 сделали в прослойке IOCP твои дельфиньи братья по разуму - я бегло гуглил, есть такие библиотеки
                                посмотри на их апи, может что и приглянётся

                                в крестах asio же способ подписаться проще пареной репы:
                                mysocket.async_receive(буфер, коллбек);
                                Ответить
                                • Ну так видишь, значит с чистым winsock.hpas окно - нормальный способ
                                  Ответить
                                  • > окно - нормальный способ
                                    На безрыбье и рак рыба.

                                    Просто в чем смысл работы с чистым winapi? Научиться работать с чистым winsock? Сделать ниибаца миниатюрную прогу в 60кб? Просто нравится мазохизм?
                                    Ответить
                                    • А чё мазохизм, в ней всё логично. Багов, связанных чисто с сетью, нет. Есть некоторые баги уже в логике на уровень выше, но не более. А так я успешно зарубился с корешом, живущим в другом районе.
                                      Ответить
                                • Люди дрочат на лапшу коллбеков, когда белые господа давно юзают async. Как там погодка, в стазисе?
                                  Ответить
                                  • ты как-то отстал от жизни, белый господин
                                    в бусте есть coroutine и asio с ним замечательно дружит
                                    работает даже в с++03
                                    http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/example/cpp03/http/server4/server.cpp
                                    другое дело, что далеко не каждый белый господин вообще понимает, как именно работает его async
                                    Ответить
                                    • > в бусте
                                      В бусте нет одного - подсветки синтаксиса в примерах ;(
                                      Ответить
                                      • бложик автора, например
                                        http://blog.think-async.com/2009/07/wife-says-i-cant-believe-it-works.html
                                        Ответить
                                        • круто.

                                          правда мне это немного напоминило перл и почему я не пишу one-liners: если оно работает, то хорошо; но если что-то ломается, то хер концы найдешь.
                                          Ответить
                                    • Это было на тему
                                      >в крестах asio же способ подписаться проще пареной репы:
                                      > mysocket.async_receive(буфер, коллбек);

                                      Белые люди и не должны понимать до поры до времени, у них просто все работает.
                                      Ответить
                                      • > до поры до времени
                                        именно поэтому я сейчас как грязный раб сижу, вспоминаю кресты, и пишу на коленке хайлоад крестосервер, который должен разгрузить чудо ынтерпрайзной мысли jboss

                                        ирония судьбы ёпт
                                        Ответить
                                        • Хайлоадщик?
                                          Ответить
                                          • нет, просто халявщик
                                            в мире ынтерпрайза нетекущее непадающее крестоприложение уже охуительный хайлоад на сверхсветовых скоростях
                                            Ответить
                                            • >нетекущее непадающее крестоприложение уже охуительно
                                              Починил
                                              Ответить
                                              • ненетекущее ненепадающее некрестоприложение неуже неохуительно
                                                Изыди, окаянный!
                                                Ответить
                                              • что, никогда не сумел написать такое?
                                                далеко не каждый сможет
                                                Ответить
                                                • >что, никогда не сумел написать такое?
                                                  Даже не пытался, разве что хелловерлд.
                                                  Ответить
                                                  • > разве что хелловерлд
                                                    И тот упал и потёк?
                                                    Ответить
                                                    • Не успел потечь :) А вот факап при попытке изменить строку из argv ловил.
                                                      Ответить
                                                      • > при попытке изменить строку из argv ловил
                                                        Вот точку входа вот вполне можно было переделать в жабоподобный int main(const std::vector<std::string> &args). Но не стали из-за ебучей совместимости ;(

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

                                                        Кресты, имхо, надо преподавать без сишного бекграунда, и вообще не упоминая о сишных методах работы... Кому надо - разберется, а остальным сишные знания только навредят.
                                                        Ответить
                                                        • > Вот точку входа вот вполне можно было переделать в жабоподобный int main(const std::vector<std::string> &args).

                                                          Только для проектов "new STL application". Это не всегда нужно.

                                                          Но приучать людей к тому, что STL Application - это и есть крестопрограмма по умолчанию - нужно.
                                                          Ответить
                                                          • > Это не всегда нужно.
                                                            Это нужно всегда. Потеря производительности тут копеечная, по сравнению со стартом приложения, зато кучу граблей убирает.

                                                            Просто делать это надо было сразу при зарождении крестов, ибо сейчас уже поздно.
                                                            Ответить
                                                            • > сразу
                                                              при зарождении STL, что случилось лет эдак 10 после официального зарождения крестов
                                                              Ответить
                                                              • > при зарождении STL
                                                                Но стринг то был изначально? Или в первых крестах даже его не было?
                                                                Ответить
                                                                • если честно - я не уверен, какой он был в 1983
                                                                  но сейчас стринг - если кто забыл - это std::basic_string<char, std::char_traits<char>, std::allocator<char>>
                                                                  Ответить
                                                            • СТЛ - это всё-таки всего лишь библиотека, и завязывать язык на неё жёстко - это против идеологии.
                                                              Ответить
                                                              • > и завязывать язык на неё жёстко - это против идеологии.
                                                                И тем не менее в крестах11 на это слегка (не так сильно как в яве) насрали, и сделали for по итераторам, initializer list и прочие фишечки, привязывающие язык к стандартной либе...
                                                                Ответить
                                                                • Нет, ты можешь и в своей библиотеке сделать так, чтобы все эти фишечки работали. Они привязаны не к конкретным типам СТЛ, а к эээ... интерфейсам, я б так сказал.
                                                                  Ответить
                                                                  • > а к эээ... интерфейсам, я б так сказал.
                                                                    Ну с фором я согласен. А с std::initializer_list как быть?
                                                                    Ответить
                                                                    • А что с ними? Я просто не в курсе.
                                                                      Ответить
                                                                      • > А что с ними?
                                                                        Ну компилятору надо что-то вставить вместо него. Но что?
                                                                        Ответить
                                                                        • Вместо чего? Я не в теме.
                                                                          Ответить
                                                                          • mytype foo = {1, 2, 5, 13};
                                                                            foo.add({7, 2, 3});
                                                                            Ответить
                                                                            • И без подключения СТЛ эта конструкция даже скомпилироваться не может?
                                                                              Ответить
                                                                              • конструкция {......} имеет тип std::initializer_list<T>
                                                                                которую ты можешь соответствующим образом обрабатывать в конструкторах, методах и т.д.

                                                                                не подключив <initializer_list> (или хоть-что нибудь из stl, что включит его за тебя), у тебя не особо выйдет каменный цветок
                                                                                http://ideone.com/wDH4y1
                                                                                Ответить
                                                                                • А как реализован std::initializer_list<T>? Можно ли его аналог реализовать самому?
                                                                                  Ответить
                                                                                  • компилятором реализован
                                                                                    о чем @bormand и начал говорить
                                                                                    что синтаксическая конструкция в с++11 незаметно получила четкую привязку к std::, хочешь ты этого в гейдеве или нет
                                                                                    Ответить
                                                                                    • Тарас, кончай жмотиться, подключай стл. тебе уже маленький хедер с инициалайзер_лист жаба давит подключить? Нед же блин, хочется свой инициалайзер_лист написать...
                                                                                      Ответить
                                                                                    • > компилятором реализован
                                                                                      Не понял, это как.
                                                                                      Что написано в заголовке с инициалайзер_листом? Можно ли это скопировать?
                                                                                      Ответить
                                                                                  • > Можно ли его аналог реализовать самому?

                                                                                    Похоже что нет. Попробовал скопипастить довольно тривиальный код из stl и использовать его для инициализации, получил от компилятора
                                                                                    prog.cpp:68:19: error: could not convert ‘{1, 2, 3, 4, 5}’ from ‘<brace-enclosed initializer list>’ to ‘initializer_list<int>’
                                                                                      f({1, 2, 3, 4, 5});
                                                                                                       ^
                                                                                    http://ideone.com/b8PC30
                                                                                    Ответить
                                                                                    • Бля какой пиздец.
                                                                                      А ведь я помню, как кое-какие крестобляди обсирали Дельфи за то, что тип string вшит в язык и Аду за то, что тип Controlled вшит в язык!
                                                                                      КРЕСТОБЛЯДИ ВЫ СОСНУЛИ111
                                                                                      Ответить
                                                    • > > разве что хелловерлд
                                                      > И тот упал и потёк?
                                                      http://ideone.com/t8hyiw
                                                      Ответить
                            • > реактор на udp по самобытному протоколу
                              Для игрушек udp, имхо, само то.
                              Ответить
                              • а ты думаешь я написал udp чтобы лишний раз унизить Taraß?
                                Ответить
                              • Мне было в падлу следить за корректностью, потому я взял тцп.
                                К тому же у мен всё держится на битовой точности - ведь пересылаются лишь базовое состояние и команды, а не координаты.
                                Ответить
                                • с другой стороны надо помнить, что tcp - это поток, потому может клеить команды вместе и рвать их на порции в самом неподходящем байте

                                  не буду кэпствовать, должен сам знать
                                  Ответить
                                  • Да, и к счастью, это происходит так часто, что это проявляется на самых ранних стадиях отладки.
                                    Я на это сразу же нарвался. Потом мне сказали, что это "алгоритм наглого". Я это учёл, всё ок.
                                    Ответить
                                    • > алгоритм наглого
                                      Кстати попробуй его отключить. Должно вроде как отзывчивость повысить, если пакеты мелкие и редкие.
                                      Ответить
                                      • не вроде, а должно
                                        это вообще первое дело при работе с мелкими пакетами
                                        Ответить
                                        • А, его отключать можно?
                                          Ответить
                                          • > А, его отключать можно?
                                            Да, можно.
                                            Ответить
                                            • Бля, чувствую себя практегом.
                                              Ответить
                                            • можно, ну только ты, Тарас, не путай nagle алгоритм и общие принципы tcp, что я написал выше

                                              первый - это всего-лишь о буферизации на этапе отправки
                                              на этапе прохождения по сети ты всё равно получишь все эффекты, просто их будет заметно меньше
                                              Ответить
                                              • Ну то есть код приёма сообщения менять не надо и пусть он учитывает что это "поток", но наглый алгоритм всё равно лучше отключить
                                                Ответить
                                                • > но наглый алгоритм всё равно лучше отключить
                                                  Так точно.

                                                  И пакеты отправляй целиком, за один write (хотя ты и так поди это делаешь).
                                                  Ответить
                                                  • Какой write? Там же send.
                                                    За один раз он у меня вроде не пропихивался, потому что я обнаружил в коде такой цикл:
                                                    procedure SendM(S: TSocket; var M: TMessage);
                                                      var
                                                        C: PChar;
                                                        Sz, Sn: integer;
                                                      begin
                                                        C := @M;
                                                        Sz := GetSize(M);
                                                        repeat
                                                          Sn := Send(S, C^, Sz, 0);
                                                          if Sn < 0 then Break;
                                                          Inc(C, Sn);
                                                          Dec(Sz, Sn);
                                                        until Sz <= 0;
                                                      end;
                                                    Ответить
                                                    • > Какой write? Там же send.
                                                      Ты не поверишь, но на сокетах работают и обычные функции для чтения и записи ;)

                                                      > until Sz <= 0;
                                                      А, да это то как раз нормально. Если пакеты не влезают в буфера - тут ты уже бессилен.

                                                      Я про другую ситуацию - когда длину сообщения отправляешь одним send'ом, а потом вторым send'ом в догонку сами данные. Без наглого они улетят двумя отдельными пакетами, что совсем не айс. А с наглым и того хуже...
                                                      Ответить
                                                      • А, не, у меня это один пакет, конечно же... Просто в потоке врезается кусок, который должен быть нчалом сообщений, и который косвенным образом определяет длину сообщения.
                                                        Ответить
                                                        • Ага, вот оно, видимо у меня там заведён "кольцевой" буфер, на самом деле с кольцом я поленился, поэтому тупо двигаю байты буфера в начало каждый раз
                                                          function RecvToBuffer(var S: TBufferedSocket; var M: TMessage; First: boolean = false): TRecBufferResult;
                                                            var
                                                              Sz, Rc: integer;
                                                              Empty: boolean;
                                                            begin
                                                              Sz := 0;
                                                              if S.First = S.Last then Empty := True else begin        // если буфер пуст, то говорить не о чем
                                                                Sz := GetKindSize(TMsgKind(S.Buffer[S.First]));
                                                                Empty := Sz > S.Last - S.First                          // что буфер достаточно заполнен
                                                              end;
                                                          
                                                              if Empty then begin                                       // если буфер плохо заполнен
                                                                Move(S.Buffer[S.First], S.Buffer[0], S.Last - S.First); // если данных мало, то сдвинем, их немного, не страшно
                                                                Dec(S.Last, S.First);
                                                                S.First := 0;                                           // сдвигаем
                                                                Rc := Recv(S.Socket, S.Buffer[S.Last], Length(S.Buffer) - S.Last, 0);  // принимаем новую порцию
                                                                if Rc <= 0 then begin
                                                                  Result := rbDisconnect;           // сдвигаем указатель на конец
                                                                  Exit;
                                                                end else Inc(S.Last, Rc);
                                                                Sz := GetKindSize(TMsgKind(S.Buffer[S.First]));
                                                                Empty := Sz > S.Last - S.First;                                        // смотрим, хватит ли данных теперь
                                                              end;
                                                          
                                                              if Empty then Result := rbEmpty else begin
                                                                Move(S.Buffer[S.First], M, Sz);
                                                                Inc(S.First, Sz);
                                                                Result := rbIsMes;
                                                              end;
                                                            end;
                                                          Ответить
                                                          • > поэтому тупо двигаю байты буфера в начало каждый раз
                                                            Я тоже так делал, потому что тупо и железобетонно ;) А с кольцами есть тыща шансов что-нибудь забаговать.

                                                            P.S. Может перед move стоит добавить проверку, что first > 0?
                                                            Ответить
                                                            • да там один хуй двигать почти нечего, из сети принимать больше времени потратишь, размер сообщения захардкожен милипиздрической величиной:
                                                              type TMsgKind = (
                                                                  mkTryJoin, mkWelcome, mkGTFO, mkChatMessage, mkChgTeam, mkStartGame, mkChangeInfo, mkGameData
                                                                );
                                                              
                                                                type TReason = (
                                                                  rUnknown, rExist, rBanned, rClosed, rFull, rYetInGame, rDisconnect
                                                                );
                                                              
                                                                type TCtrl = string [31];
                                                                type TName = string [23];
                                                                type TText = string [135];
                                                                type TStartData = array [0 .. 63] of byte;
                                                                type TGameData = array [0 .. 31] of byte;
                                                              
                                                                type TClientState = (cisOpened, cisClosed, cisBanned, cisNew, cisBot, cisPlayer);
                                                                type TClientInfo = record
                                                                  State: TClientState;
                                                                  Team: integer;
                                                                  Name: TName;
                                                                end;
                                                              
                                                                type TMessage = packed record
                                                                  case MsgKind: TMsgKind of
                                                                    mkTryJoin: (
                                                                      tjCtrl: TCtrl;
                                                                      tjName: TName;
                                                                    );
                                                                    mkWelcome: (
                                                                      wNumber: integer;
                                                                      wMaxClients: integer;
                                                                      wTeam: integer;
                                                                      wGameName: TName;
                                                                      wBytes: TStartData;
                                                                    );
                                                                    mkGTFO: (
                                                                      gtfoReason: TReason;
                                                                    );
                                                                    mkChatMessage: (
                                                                      cmGamer: integer;
                                                                      cmOnlyAlly: boolean;
                                                                      cmText: TText;
                                                                    );
                                                                    mkStartGame: ();
                                                                    mkChangeInfo: (
                                                                      ciNumber: integer;
                                                                      ciOldInfo: TClientInfo;
                                                                      ciNewInfo: TClientInfo;
                                                                    );
                                                                    mkGameData: (
                                                                      gdTaktNumber: int64; // ололо
                                                                      gdGamer: integer;
                                                                      gdBytes: TGameData;
                                                                    );
                                                                end;

                                                              блин в первый раз наверное, смотрю на свой старый код и не хочется плеваться
                                                              Ответить
                                                            • а вы не пробовали просто читать ровно столько, сколько вам нужно? зачем эти игры с буфером?
                                                              Ответить
                                                              • Изначально так и пробовал, но был какой-то облом почему-то с наглым алгоритмом.
                                                                Ответить
                                                                • нет, ты не понял
                                                                  допустим, ты знаешь, что твой пакет состоит из двух частей - с известной длиной (хедер) и переменной
                                                                  читаешь хедер - например, он 40 байт, ты выделяешь буфер на 40 байт (можно и не в куче, если чо), спрашиваешь сокет - дай 40 байт вот сюда
                                                                  допустим тебе сокет отвечает "на пока 30 байт, это всё что есть",
                                                                  ты говоришь "ок, на тебе указатель на то место, где я хочу видеть оставшиеся 10 (это твой буфер + смещение 30)" - сокет тебе их туда дочитывает
                                                                  ты принял хедер, видишь, что переменная часть - 1243 байта,
                                                                  говоришь сокету - на тебе буфер на 1243 байта, читай,
                                                                  далее по той же схеме

                                                                  я так понял, вы вычитываете заодно "чужие" байты - из следующего пакета
                                                                  так делать нехорошо
                                                                  Ответить
                                                                  • А чё чужие-то. Порт мой, чё такого считать заранее из будущего пакета
                                                                    Ответить
                                                              • > а вы не пробовали просто читать ровно столько, сколько вам нужно?
                                                                Х.з., мне казалось, что чем меньше я буду дергать read() - тем лучше, все-таки syscall и все такое... Поэтому по ивенту от реактора просил читать сразу до конца буфера, а потом все что пришло - разгребал while'ом и сдвигал недопарсенный остаток в начало.

                                                                Может быть и зря я экономил эти read'ы...

                                                                А на проакторе в asio я уже читал сколько нужно.
                                                                Ответить
                                                                • если пишешь роутер, то там уже надо считать копейки, замерять пропускную способность, думать об Intel DPDK и других громких аббревиатурах
                                                                  Ответить
                                                      • >Ты не поверишь, но на сокетах работают и обычные функции для чтения и записи ;)
                                                        На винде это не так. Там сокеты и файловые типа дескрипторы - это совсем разные вещи. ЕМНИМ, для последних есть отдельно дескрипторы винапи (CreateFile, ...) и дескрипторы UNIX-стайл (_open, _write, _read)..
                                                        Ответить
                                                        • > совсем разные вещи
                                                          Да ну, вроде ридфайл работал на них... или я туплю?
                                                          Ответить
                                                          • > Да ну, вроде ридфайл работал на них... или я туплю?
                                                            Да, я туплю. Прочитал ман - сокетные функции юзают SOCKET, файловые - HANDLE.
                                                            Ответить
                                                            • http://msdn.microsoft.com/en-us/library/ms740522.aspx
                                                              Ответить
                                                              • > http://msdn.microsoft.com/en-us/library/ms740522.aspx
                                                                Т.е. все-таки я был прав ;)

                                                                Там поди typedef HANDLE SOCKET?
                                                                Ответить
                                                                • емнип, это всё void *, поэтому можно не тайпдефиться лишний раз
                                                                  Ответить
                                                                  • > это всё void *
                                                                    у меня сложилось впечатление, что всё таки
                                                                    typedef unsigned int SOCKET;
                                                                    Ответить
                                                                    • ты прав
                                                                      ::SOCKET sock;
                                                                      ::WriteFile((HANDLE)sock, ...
                                                                      :)
                                                                      Ответить
                                                                    • > у меня сложилось впечатление, что всё таки
                                                                      > typedef unsigned int SOCKET;
                                                                      Пускай кто-нибудь проверит, у кого есть виндовый компилятор ;)
                                                                      Ответить
                                                    • ну а как ты хотел? отправить гигабайт и чтобы он положился сразу в системный буфер, а тебе сказал спасибо?
                                                      вот твоя библиотека и решает за тебя эту маленькую проблему - кормит сокет порциями, сколько он сам может пережевать
                                                      Ответить
                                    • >Потом мне сказали, что это "алгоритм наглого"
                                      И ты его отключил и теперь все читается как пишется? Убейте эту макаку.
                                      Ответить
                                      • > И ты его отключил и теперь все читается как пишется?
                                        Ты читать вообще умеешь? Или чукча не читатель, чукча писатель? Тарас ведь даже код кинул, как он читает эти сокеты...

                                        А отключают нагеля совсем не для того, чтобы "читалось как пишется", а просто чтобы убрать бесполезную в случае мелких и редких пакетов задержку.
                                        Ответить
                                        • >> все читается как пишется?
                                          > Ты читать вообще умеешь?
                                          я думаю, аноним возмущается по поводу nagle -> наглый
                                          Ответить
                                          • Нет, я думал вот что: он отключил нагла и исходит из того, что каждой записи на одном конце соответствует чтение на другом.
                                            Ответить
                                      • >Ты читать вообще умеешь? Или чукча не читатель, чукча писатель? Тарас ведь даже код кинул, как он читает эти сокеты...
                                        Почему такой батхерт? Не умею я читать байтоебскую паскальщину, разучился :) Расскажите, че там, он их в буфер сливает?
                                        Ответить
                                        • > Не умею я читать байтоебскую паскальщину, разучился :)

                                          Тяжело да?
                                          Ответить
                                        • > че там, он их в буфер сливает
                                          Ну. Выгребает из буфера целые пакеты, а когда таких не остается - сдвигает буфер до упора влево и дочитывает из сокета еще.
                                          Ответить
                                  • > может клеить команды вместе и рвать их на порции
                                    Там еще очень неприятная херня есть с write-write-read. У меня терминальчик по гигабитной локалке из-за этой фигни работал как по сраному диалапу :)
                                    Ответить
                                • Там не только подтверждение, там много что, втч защита от слепого спуфинга, например :)
                                  Ответить
                      • > И чем невидимое окно-подписчик хуже?
                        Надо тебя в ссылку к пингвинам на пару лет. Там ты быстро научишься не юзать окна для неподобающих целей :)

                        А если серьезно: невидимый объект-подписчик - нормальное решение (в том же Qt так и разруливается работа с сокетами). А то, что делфя умеет роутить события только окнам - это уже делфипроблемы.
                        Ответить
              • Бля, промахнулся и влепил плюс. толсто. Хотя гуй подсистема работающая под админом и при падении тянущая за собой всю систему это не то, что нужно на сервере.
                Ответить
          • Кстати говоря, дефекейт сказал "зачем работать с сокетом неасинхронно" а не "зачем работать с сокетом асинхронно". Т.е. он за асинхронную работу, как и ты (но всяко против роутинга этих событий через какое-то там окно).
            Ответить
            • Подожди, синхронно - это одновременно, а асинхронно - это по очереди? Ааа, тогда да, он прав.
              А чё его минуснули? Крутой комент же, потому что
              1) рвёт быдлошаблоны быдлоынтерпрайза
              2) я тоже так делаю
              Ответить
              • От количества ничего не зависит.

                Синхронный код прост и понятен - например функция, которая в цикле использует блокирующий read() и возвращает результат. Да, чтобы таким способом читать несколько файлов понадобится несколько потоков (или псевдосинхронные штучки в духе async/await или yield, о которых мы умолчим).

                Асинхронный же код выглядит как ёбаная лапша использует неблокирующие операции ввода-вывода и неким образом просит операционку, чтобы она оповещала в нужное время. Есть две модели - реактор и проактор. В реакторе нас извещают о том, что на сокете есть данные (select/poll/то что ты рассказывал с окном), в проакторе мы просим прочитать данные, а ось уведомляет нас, что все прочиталось. Асинхронный код можно исполнять в однин поток, но при желании и умении можно и в несколько.

                Как-то так.
                Ответить
                • >или псевдосинхронные штучки в духе async/await или yield, о которых мы умолчим).
                  Пардон, а чем await не асинхронный? Без него асинхронность поддерживается вызовами/твоей прогой, с ней асинхронность добавляется языком.
                  Ответить
                  • > Пардон, а чем await не асинхронный?
                    Он асинхронный. Но код с ним выглядит как синхронный (т.е. не как лапша).
                    Ответить
                    • Может, ты имел в виду, что за ним все равно стоит синхронный код (т.е. блокирующие операции)? Разница какая-то есть?
                      Ответить
                      • Не, я просто затупил и не к той группе его отнес. Он асинхронный, всяко юзает неблокирующие операции, и делает абсолютно то же самое, что и лапша коллбеков. Так что правильнее относить его все-таки к асинхронному.

                        Просто с точки зрения программиста выглядит он как синхронный и блокирующий.

                        Ответить
          • это не костыль, это мегакостыль. чувак, может приход у тебя?
            Ответить
          • Ein Kern
            Ein Thread
            Ein Taraß
            Ответить
    • vanished
      Ответить

    Добавить комментарий