1 2 3
Re[12]: сериализация данных в избранное  новое горячее всё    подписка   модер. 
От: k732 
Дата: 13.06.07 13:28
Здравствуйте, Sergey, Вы писали:


>> Спасибо за код. Буду разбираться.

>> С записью понятно — заранее известен размер данных. А как с чтением, если размер данных, которые прийдут не известен (или будет известен только из заголовка пакета)

S>Ну а кто мешает просто пытаться читать сколько просят? Или на уровне device отслеживать заголовки пакетов? В общем, какой протокол придумаете, так и будет работать.



Тоесть всегда просить максимум ?

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


С промежеточным буером работает. А вот как сразу писать в поток, чтоб потом десериализовать — пока не соображу
Re[11]: сериализация данных в избранное  новое    модер. 
От: . 
Дата: 13.06.07 13:36
k732 wrote:

> тоесть реально я буду писать в вектор,

Куда сделаешь, туда и будешь писать. Ты сам определяешь куда писать в методе write. Например, в сокет будет примерно так:
 >     std::streamsize write(const char_type* s, std::streamsize n)
 >     {
mysocket_.write(s, n);
 >         return n;
 >     }


> а в архив отдавать его оберну в container_sink ?

Ниче не понял. Архив принимает ostream, а sink им и является.
Posted via RSDN NNTP Server 2.1 beta
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[12]: сериализация данных в избранное  новое    модер. 
От: k732 
Дата: 13.06.07 13:38
Здравствуйте, ., Вы писали:

>> а в архив отдавать его оберну в container_sink ?

.>Ниче не понял. Архив принимает ostream, а sink им и является.

Блин — тогда я совсем запутался
Никогда просто с потоками не работал....
Re[13]: сериализация данных в избранное  новое    модер. 
От: Sergey 
Дата: 13.06.07 13:56
>>> Спасибо за код. Буду разбираться.
>>> С записью понятно — заранее известен размер данных. А как с чтением, если размер данных, которые прийдут не известен (или будет известен только из заголовка пакета)
>
> S>Ну а кто мешает просто пытаться читать сколько просят? Или на уровне device отслеживать заголовки пакетов? В общем, какой протокол придумаете, так и будет работать.
>
>
> Тоесть всегда просить максимум ?
>
> Если у вас уже что-то работает с копированием данных в промежуточный буфер, то не составит большого труда переделать это на использование стримов.
>
>
> С промежеточным буером работает. А вот как сразу писать в поток, чтоб потом десериализовать — пока не соображу

Сколько просить — зависит от того, как у вас устроена десериализация. Лучше всего опишите, как оно сейчас работает — тогда может что-нибудь и придумается. Принимаете пакет (длина — в заголовке), складываете его в буфер — это я понял. А дальше что с ним делаете?
Posted via RSDN NNTP Server 2.1 beta
На улицах злая гопота, в офисах злые гомосеки.
Как выжить в этом городе простому человеку?
Re[14]: сериализация данных в избранное  новое    модер. 
От: k732 
Дата: 13.06.07 15:04
S>Сколько просить — зависит от того, как у вас устроена десериализация. Лучше всего опишите, как оно сейчас работает — тогда может что-нибудь и придумается. Принимаете пакет (длина — в заголовке), складываете его в буфер — это я понял. А дальше что с ним делаете?

ну работает так. Я сериализую класс и получаю массив байт (ну например достаю из потока).
У сокета есть методы read/write

std::size_t Socket::read  (unsigned char buffer[], std::size_t size);
std::size_t Socket::write (unsigned char buffer[], std::size_t size);


Для того, чтоб было понятно сколько запрашивать данных, в начале каждого блока идет заголовок.


enum TYPE    { ... };
enum SUBTYPE    { ... };
enum RESULT    { ... ;
enum STATE    { ... };

struct HEADER 
{
    TYPE    type;
    SUBTYPE    subtype;
    COMMAND    command;
    union 
    {
        unsigned value;
        RESULT     result;
        STATE     state;
    };

    HEADER () : type ((TYPE)0), subtype ((SUBTYPE)0),
        command ((COMMAND)0), value (0){}
    HEADER (TYPE wfType, SUBTYPE wfSubtype, COMMAND wfCommand)
        : type (wfType), subtype (wfSubtype), command (wfCommand), value (0){}
    ~HEADER() {}

};



Работает все хозяйство по принципу запрос-ответ.

Например. Клиент запрашивает данные, отправляя заголовок с нужным кодом.
Сервер всегда знает размер заголовка, по.тому читает его. Далее сериализует данные и
отправляет сначала заголовок, в котором говорит размер данных, а потом данные.
Клиент прочитав заголовок, понимает сколько нужно ждать данных. Читает их и десериализует.

Так вот раньше сериализация и десериализация выполнялась руками. Это много кода и я решил прикрутить boost.
Но вся проблемма в том, что класс сокет читает и пишет в память (прототип я привел), а бусттовский архив работает с потоками.

Так вот и возник вопрос чтения и записи сразу в поток. Но писать понятно как, а вот читать...
Re[13]: сериализация данных в избранное  новое    модер. 
От: . 
Дата: 13.06.07 15:21
k732 wrote:

>> > а в архив отдавать его оберну в container_sink ?

> .>Ниче не понял. Архив принимает ostream, а sink им и является.
>
> Блин — тогда я совсем запутался
> Никогда просто с потоками не работал....
А что тут такого... read, write, очень похоже на сокеты.
Просто тебе не обязательно в начале передавать размер данных, и даже не обязательно знать этот размер. Концом пакета
можно сделать, скажем '\0' или если это xml, то закрытие последнего тега.
А вообще, работать напрямую с сокетами в наше время немного несовременно, есть куча протоколов, хоть тот же http
например, которые многое упрощают. С сокетами работать приходится в крайних ситуациях, когда к системе предъявляют очень
серьёзные требования быстродействия.
Posted via RSDN NNTP Server 2.1 beta
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[14]: сериализация данных в избранное  новое    модер. 
От: k732 
Дата: 13.06.07 15:27
Здравствуйте, ., Вы писали:

.>А что тут такого... read, write, очень похоже на сокеты.

.>Просто тебе не обязательно в начале передавать размер данных, и даже не обязательно знать этот размер. Концом пакета
.>можно сделать, скажем '\0' или если это xml, то закрытие последнего тега.
.>А вообще, работать напрямую с сокетами в наше время немного несовременно, есть куча протоколов, хоть тот же http
.>например, которые многое упрощают. С сокетами работать приходится в крайних ситуациях, когда к системе предъявляют очень
.>серьёзные требования быстродействия.

Да как-то поперло еще давно. Переделывать не хочется. Много завязано на классах.
Надо просто прикрутить boost.

Может конечно есть и проще решение. Может также и писать в память
а просто потом заставить архив сериализовать его. Это можно сделать ?

Наверное нужны обертки или вот я нашел там что-то похожее basic_array который может и сможет помоч
Re[15]: сериализация данных в избранное  новое    модер. 
От: . 
Дата: 13.06.07 15:45
k732 wrote:

> Да как-то поперло еще давно. Переделывать не хочется. Много завязано на

> классах.
> Надо просто прикрутить boost.
Определяешь методы read/write чтобы они валили всё в сокет и всё вроде... Но размер-то тебе неизвестен, если ты
используешь заголовок с длиной, то ничего не получится. Или есть какой-то способ вычислить размер данных до генерации до
сериализации?

> Может конечно есть и проще решение. Может также и писать в память

> а просто потом заставить архив сериализовать его. Это можно сделать ?
А какого примерно размера пакеты?

> Наверное нужны обертки или вот я нашел там что-то похожее basic_array

> который может и сможет помоч
Да, можно. Хотя ведь есть std::stringstream, но он несколько неоптимально с памятью работает...
Posted via RSDN NNTP Server 2.1 beta
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[16]: сериализация данных в избранное  новое    модер. 
От: k732 
Дата: 13.06.07 15:59
Здравствуйте, ., Вы писали:

.>k732 wrote:


.>Определяешь методы read/write чтобы они валили всё в сокет и всё вроде... Но размер-то тебе неизвестен, если ты

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

к сожалению нет.

>> Может конечно есть и проще решение. Может также и писать в память

>> а просто потом заставить архив сериализовать его. Это можно сделать ?
.>А какого примерно размера пакеты?

данные могут быть любой длинны


>> Наверное нужны обертки или вот я нашел там что-то похожее basic_array

>> который может и сможет помоч
.>Да, можно. Хотя ведь есть std::stringstream, но он несколько неоптимально с памятью работает...

единственное меня смутило, что basic_array это обертка над памятью фиксированного размера.
Тоесть после ее создания размер не пожет менятся. А это значит что можно только десериализовать с помощью ее.


Блин да почему все так сложно в такой мощной библиотеке. Мне данные в чистом виде не нужны.
Нужен лишь десериализованный объект. А приходится работать побайтно.

А чем может помоч http и есть ли он в boost ?
Re[12]: сериализация данных в избранное  новое    модер. 
От: k732 
Дата: 13.06.07 16:56
Здравствуйте, ., Вы писали:

.>k732 wrote:


>> тоесть реально я буду писать в вектор,

.>Куда сделаешь, туда и будешь писать. Ты сам определяешь куда писать в методе write. Например, в сокет будет примерно так:
.>
 >>     std::streamsize write(const char_type* s, std::streamsize n)
 >>     {
.>mysocket_.write(s, n);
 >>         return n;
 >>     }
.>


>> а в архив отдавать его оберну в container_sink ?

.>Ниче не понял. Архив принимает ostream, а sink им и является.

1. так container_sink и container_source решат проблемму ? (просто там приведены общие примеры для контейнеров и не совсем понятно нужно ли самому писать или они уже написали обший для оборачивания контейнера)
2. И можно ли сразу и для записи и для чтения сделать ?
3. Может уже есть такие шаблоны для контейнеров ?
4. Какой контейнер лучше использовать ?

там примеры

namespace boost { namespace iostreams { namespace example {

template<typename Container>
class container_sink {
public:
    typedef typename Container::value_type  char_type;
    typedef sink_tag                        category;
    container_sink(Container& container) : container_(container) { }
    std::streamsize write(const char_type* s, std::streamsize n)
    {
        container_.insert(container_.end(), s, s + n);
        return n;
    }
    Container& container() { return container_; }
private:
    Container& container_;
};

} } } // End namespace boost::iostreams:example


и

template<typename Container>
class container_source {
public:
    typedef typename Container::value_type  char_type;
    typedef source_tag                      category;
    container_source(Container& container) 
        : container_(container), pos_(0)
        { }
    std::streamsize read(char_type* s, std::streamsize n)
    {
        using namespace std;
        streamsize amt = static_cast<streamsize>(container_.size() - pos_);
        streamsize result = (min)(n, amt);
        if (result != 0) {
            std::copy( container_.begin() + pos_, 
                       container_.begin() + pos_ + result, 
                       s );
            pos_ += result;
            return result;
        } else {
            return -1; // EOF
        }
    }
    Container& container() { return container_; }
private:
    typedef typename Container::size_type   size_type;
    Container&  container_;
    size_type   pos_;
};

} } } // End namespace boost::iostreams:example
Re[17]: сериализация данных в избранное  новое    модер. 
От: . 
Дата: 13.06.07 17:58
k732 wrote:

> .>Определяешь методы read/write чтобы они валили всё в сокет и всё

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

>> > Может конечно есть и проще решение. Может также и писать в память

>> > а просто потом заставить архив сериализовать его. Это можно сделать ?
> .>А какого примерно размера пакеты?
> данные могут быть любой длинны
Ну в смысле 3 гигабайта может быть? Тогда у тебя в принципе не получится всё сериализовать в память (по крайней мере на
x86).

>> > Наверное нужны обертки или вот я нашел там что-то похожее basic_array

>> > который может и сможет помоч
> .>Да, можно. Хотя ведь есть std::stringstream, но он несколько
> неоптимально с памятью работает...
> единственное меня смутило, что basic_array это обертка над памятью
> фиксированного размера.
> Тоесть после ее создания размер не пожет менятся. А это значит что можно
> только десериализовать с помощью ее.
Так там просто пример, что поток вокруг чего угодно можно навернуть... В доке, что я посылал тебе выше, есть код для
оборачивания любого контейнера, имеющего insert, есть код для std::string, чем не нравится? Можешь прикрутить std::vector.

> Блин да почему все так сложно в такой мощной библиотеке. Мне данные в

> чистом виде не нужны.
> Нужен лишь десериализованный объект. А приходится работать побайтно.
Так просто там всё. Просто твоя задача слишком простая, что конкретно её никто решать не собирается, там обобщённое
решение, разберись.

> А чем может помоч http и есть ли он в boost ?

В бусте нету. А чем помочь — это протокол, к которому есть куча библиотек для работы с ним, позволяет передавать данные
с некой метаинформацией, позволяет легко перейти на использование защищённого канала (https), бегать через прокси и т.п.
Т.е. не надо придумывать как передать длину — есть content-length, не нужно придумывать как передать тип инфы — есть
content-type. Легко прикручивается gzip для компрессии, можно кэши настраивать. В общем куча преимуществ готового и
отлаженного решения.
Posted via RSDN NNTP Server 2.1 beta
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[13]: сериализация данных в избранное  новое    модер. 
От: . 
Дата: 13.06.07 18:11
k732 wrote:

> 1. так container_sink и container_source решат проблемму ? (просто там

> приведены общие примеры для контейнеров и не совсем понятно нужно ли
> самому писать или они уже написали обший для оборачивания контейнера)
Да я не знаю.. Вроде всё написано. Или с английским плохо?

Suppose you want to write a Device for appending characters to an STL container.


> 2. И можно ли сразу и для записи и для чтения сделать ?

Можно. Там всё написано.
http://boost.org/libs/iostreams/doc/tutorial/container_device.html

> 3. Может уже есть такие шаблоны для контейнеров ?

Какие именно "такие"?

> 4. Какой контейнер лучше использовать ?

Самый лучший.

Короче, у тебя теоретических знаний не хватает, по-моему. Что такое stream даже не понимаешь, именно как абстрактное
понятие, а не связанное с С++.
Поизучай Haskell что-ли...
Posted via RSDN NNTP Server 2.1 beta
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[15]: сериализация данных в избранное  новое    модер. 
От: Sergey 
Дата: 13.06.07 18:49
Здравствуйте, k732, Вы писали:

S>>Сколько просить — зависит от того, как у вас устроена десериализация. Лучше всего опишите, как оно сейчас работает — тогда может что-нибудь и придумается. Принимаете пакет (длина — в заголовке), складываете его в буфер — это я понял. А дальше что с ним делаете?


K>Работает все хозяйство по принципу запрос-ответ.


K>Например. Клиент запрашивает данные, отправляя заголовок с нужным кодом.

K>Сервер всегда знает размер заголовка, по.тому читает его. Далее сериализует данные и
K>отправляет сначала заголовок, в котором говорит размер данных, а потом данные.
K>Клиент прочитав заголовок, понимает сколько нужно ждать данных. Читает их и десериализует.

K>Так вот раньше сериализация и десериализация выполнялась руками. Это много кода и я решил прикрутить boost.

K>Но вся проблемма в том, что класс сокет читает и пишет в память (прототип я привел), а бусттовский архив работает с потоками.

K>Так вот и возник вопрос чтения и записи сразу в поток. Но писать понятно как, а вот читать...


А, так это boost::serialization. Она читает не больше, чем ей реально нужно данных — т.е., если запрашиваемые данные не пришли, это ошибка и разумным будет подождать некоторое время и по истечении таймаута выставить ошибку и вернуть 0. Есть правда небольшая проблема — стримы буферизирует данные, т.е., если архив попытался прочитать 305 байт, в device::read придет требование например, на 4k данных. Поэтому придется установить эти буферы равного размера на обоих концах и в начале каждого пакета передавать длину. Только пакетом будет уже не все сообщние (длину которого на момент начала передачи вы не знаете), а то, что пришло в device::write.
На улицах злая гопота, в офисах злые гомосеки.
Как выжить в этом городе простому человеку?
Re: сериализация данных в избранное  новое    модер. 
От: ArtDenishttp://www.jimm.org/?ru
Дата: 14.06.07 04:57
k732 пишет:
>
> Не слишком ли много телодвижений ?

Намана
Представь себе, что ты сериализуешь данные по следующему алгоритму:

1. Блокировка изменения данных
2. Сериализация в буфер
3. Разблокировка изменения данных
4. Отправка в сокет

В этом случае у тебя данные блокируются на минимальное время, которое
можно принять за константу.

Если ты будешь сразу отправлять данные в сокет, то есть вероятность, что
время между блокировкой и разблокировкой данных возрастёт в
зависимости от состояния и загруженности физического канала,
используемого сокетом для передачи данных. Причём величина этой задержки
может быть какой угодно.

Возрастание времени, в течении которого нельзя изменять данные может
сказать на быстродействии программы. Для реального времени это
недопустимо, т.к. там такая задержка может нарушить работу алгоритмов.

Так что сериализация в буфер, а затем отправка содержимого буфера — IMHO
самый оптимальный вариант.
Posted via RSDN NNTP Server 2.1 beta
www.jimm.org — бесплатная аська для сотовых
Re[10]: сериализация данных в избранное  новое    модер. 
От: k732 
Дата: 14.06.07 06:25
Здравствуйте, Sergey, Вы писали:

Поробовал я так сделать как ты говорил, только
я как в примере сделал

typedef boost::iostreams::seekable_device_tag  category;


Вроде все сварилось кроме сериализации


typedef std::vector <unsigned char> sbuffer;
typedef container_stream <sbuffer> sdevice;
typedef boost::iostreams::stream_buffer<sdevice> sstream;

namespase parser
{
    template <class T>
    inline void serialize (sbuffer& buffer, const T& rhs)
    {
        try
        {
            sstream stream (sdevice (buffer));
            std::ostream ostream (&stream);
            boost::archive::binary_oarchive archive (ostream);
            archive << BOOST_SERIALIZATION_NVP (rhs);
        }
        catch (std::exception& ex)
        {
             std::cerr << ex.what() << std::endl;
        }
    }
}


Но говорит, что не почет конвертнуть sstream в std::ostream.
Re[11]: сериализация данных в избранное  новое    модер. 
От: Sergey 
Дата: 14.06.07 07:04
"k732" <57436@users.rsdn.ru> wrote in message news:2545323@news.rsdn.ru...
> Здравствуйте, Sergey, Вы писали:
>
> Поробовал я так сделать как ты говорил, только
> я как в примере сделал
>
>
> typedef boost::iostreams::seekable_device_tag  category;
>

>
> Вроде все сварилось кроме сериализации

seekable тут излишен. Хотя реализовать его над вектором и не составит труда. Но не над сокетами.

>

>
>
> typedef std::vector <unsigned char> sbuffer;
> typedef container_stream <sbuffer> sdevice;
> typedef boost::iostreams::stream_buffer<sdevice> sstream;
> 
> namespase parser
> {
>    template <class T>
>    inline void serialize (sbuffer& buffer, const T& rhs)
>    {
>        try
>        {
>            sstream stream (sdevice (buffer));
>            std::ostream ostream (&stream);
>            boost::archive::binary_oarchive archive (ostream);
>            archive << BOOST_SERIALIZATION_NVP (rhs);
>        }
>        catch (std::exception& ex)
>        {
>             std::cerr << ex.what() << std::endl;
>        }
>    }
> }
> 
>

>
> Но говорит, что не почет конвертнуть sstream в std::ostream.

Говорит, что &stream — указатель на функцию? Бывает Создай именованный объект sdevice, и оно скомпиляется:
        sdevice dev(buffer);
        sstream stream (dev);
        std::ostream ostream (&stream);
Posted via RSDN NNTP Server 2.1 beta
На улицах злая гопота, в офисах злые гомосеки.
Как выжить в этом городе простому человеку?
Re[12]: сериализация данных в избранное  новое    модер. 
От: k732 
Дата: 14.06.07 07:12
Здравствуйте, Sergey, Вы писали:

S>seekable тут излишен. Хотя реализовать его над вектором и не составит труда. Но не над сокетами.

А какой tag нужен тогда для read/write

S>Говорит, что &stream — указатель на функцию? Бывает Создай именованный объект sdevice, и оно скомпиляется:

S>
S>        sdevice dev(buffer);
S>        sstream stream (dev);
S>        std::ostream ostream (&stream);
S>


Не помогло

: error C2664: 'std::basic_ostream<_Elem,_Traits>::basic_ostream(std::basic_streambuf<_Elem,_Traits> *,bool)' : cannot convert parameter 1 from 'parser::sstream *__w64 ' to 'std::basic_streambuf<_Elem,_Traits> *'
2>        with
2>        [
2>            _Elem=char,
2>            _Traits=std::char_traits<char>
2>        ]
2>        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
2>        .\xxx.cpp(104) : see reference to function template instantiation 'void
Re[13]: сериализация данных в избранное  новое    модер. 
От: Sergey 
Дата: 14.06.07 07:27
> S>seekable тут излишен. Хотя реализовать его над вектором и не составит труда. Но не над сокетами.
> А какой tag нужен тогда для read/write

Для write — sink_tag, для read — source_tag. Оба сразу — bidirectional_device_tag, но с ним в 1.33.1 баги были. Исправили ли их в 1.34, не знаю.
Вообще, если заглянуть в boost\iostreams\categories.hpp, то взаимоотношения между категориями станут более понятными.

>
> : error C2664: 'std::basic_ostream<_Elem,_Traits>::basic_ostream(std::basic_streambuf<_Elem,_Traits> *,bool)' : cannot convert parameter 1 from 'parser::sstream *__w64 ' to 'std::basic_streambuf<_Elem,_Traits> *'
> 2>        with
> 2>        [
> 2>            _Elem=char,
> 2>            _Traits=std::char_traits<char>
> 2>        ]
> 2>        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
> 2>        .\xxx.cpp(104) : see reference to function template instantiation 'void
> 
>

>

А char_type у sstream какой?
Posted via RSDN NNTP Server 2.1 beta
На улицах злая гопота, в офисах злые гомосеки.
Как выжить в этом городе простому человеку?
Re[14]: сериализация данных в избранное  новое    модер. 
От: k732 
Дата: 14.06.07 07:36
Здравствуйте, Sergey, Вы писали:

S>Для write — sink_tag, для read — source_tag. Оба сразу — bidirectional_device_tag, но с ним в 1.33.1 баги были. Исправили ли их в 1.34, не знаю.

S>Вообще, если заглянуть в boost\iostreams\categories.hpp, то взаимоотношения между категориями станут более понятными.

спасибо

S>А char_type у sstream какой?

он определен через typedef T::char_type

typedef std::vector <unsigned char> sbuffer;
typedef container_stream <sbuffer> sdevice;
typedef boost::iostreams::stream_buffer<sdevice> sstream;


тоесть должен быть unsigned char
Re[15]: сериализация данных в избранное  новое    модер. 
От: Sergey 
Дата: 14.06.07 07:40
> S>А char_type у sstream какой?
> он определен через typedef T::char_type
>
>
> typedef std::vector <unsigned char> sbuffer;
> typedef container_stream <sbuffer> sdevice;
> typedef boost::iostreams::stream_buffer<sdevice> sstream;
>

>
> тоесть должен быть unsigned char
>

А чтобы скомпилировалось, должен быть просто char — либо вместо std::ostream надо использовать std::basic_ostream<unsigned char> — но не факт, что последнее понравится boost::serialization.
Posted via RSDN NNTP Server 2.1 beta
На улицах злая гопота, в офисах злые гомосеки.
Как выжить в этом городе простому человеку?
1 2 3