Модераторы: feodorv

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Передача vector<wstring>, Socket 
V
    Опции темы
Kirgston
Дата 21.11.2010, 18:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 792
Регистрация: 24.12.2007

Репутация: нет
Всего: 2



Доброго времени суток! Собственно интересует как лучше сделать передачу векторов (wstring) используя чистые сокеты (Win Api) 
PM MAIL   Вверх
azesmcar
Дата 21.11.2010, 18:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 3
Всего: 211



Цитата(Kirgston @  21.11.2010,  18:35 Найти цитируемый пост)
Доброго времени суток! Собственно интересует как лучше сделать передачу векторов (wstring) используя чистые сокеты (Win Api)  

Вектор по сети не передается. Для этого клиент и сервер договариваются о конкретном формате данных, который будет передаваться и посылают данные в этом формате. Это может быть XML или просто текст, разделенный каким-то специальным символом..это уже тебе решать.
PM   Вверх
boostcoder
Дата 21.11.2010, 18:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



так:
Код

#include <boost/serialization/string.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/archive/binary_oarchive.hpp>

#include <vector>
#include <string>
#include <sstream>
#include <iostream>

std::string send_vector_wstring(const std::vector<std::wstring>& vs) {
   std::stringstream os;
   boost::archive::binary_oarchive(os) << vs;
   return os.str();
}

int main() {
   std::vector<std::wstring> vs = {
      L"1",
      L"2"
   };
   std::cout << send_vector_wstring(vs);
}

http://liveworkspace.org/code/c3601e80b7d4...36c56a54522dc21
PM WWW   Вверх
Kirgston
Дата 21.11.2010, 23:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 792
Регистрация: 24.12.2007

Репутация: нет
Всего: 2



boostcoder, спасибо большое. Как я вижу буст переделывает вектор в бинарные данные. Тогда еще один вопросец... а как обратно то? 
PM MAIL   Вверх
boostcoder
Дата 21.11.2010, 23:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



так:
Код

#include <boost/serialization/string.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/archive/binary_iarchive.hpp>

#include <vector>
#include <string>
#include <sstream>
#include <iostream>

std::vector<std::wstring> recv_vector_wstring(const std::string& buf) {
   std::stringstream is(buf);
   std::vector<std::wstring> vs;
   boost::archive::binary_iarchive(is) >> vs;
   return vs;
}

int main() {
   std::string buf;
   std::vector<std::wstring> vs = recv_vector_wstring(buf);
}

http://liveworkspace.org/code/697afcd05c8b...a79ee2559aa90e3
PM WWW   Вверх
alexvs11
Дата 22.11.2010, 00:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


hell is here
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 21.8.2010

Репутация: 1
Всего: 10



boostcoder, а он адекватно восстановится на другом компьютере или хотя бы в другом процессе при учете аллокаторов и прочих прелестей string и vector?
PM MAIL   Вверх
boostcoder
Дата 22.11.2010, 00:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(alexvs11 @  22.11.2010,  00:31 Найти цитируемый пост)
он адекватно восстановится на другом компьютере или хотя бы в другом процессе при учете аллокаторов и прочих прелестей string и vector? 

если бы это было не так, вряд ли такой способ назывался бы сериализацией smile 
PM WWW   Вверх
Kirgston
Дата 23.11.2010, 22:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 792
Регистрация: 24.12.2007

Репутация: нет
Всего: 2



Цитата(boostcoder @  22.11.2010,  00:33 Найти цитируемый пост)
если бы это было не так, вряд ли такой способ назывался бы сериализацией 

Хм... если например зашифровать стринг и сразу же расшифровать - всё хорошо. Если же при этом передать по сети шифрованный вариант и попытаться расшифровать то вылетит эксепшен на 
"catch stream_error archive exceptions will cause invalid_signature archive exception to be thrown below" . А именно оно не может найти дочерних элементов. 

Вот код отсылки сообщения с сервера:

Код

void SendMessage( SOCKET s,std::wstring Msg )
{
    std::string str = enc.send_wstring(Msg);    
    int ret = send(s, str.c_str(),str.length(), 0);
}


Вот код приема данных в клиенте:

Код

std::wstring GetMessage()
{
    if (Connnected)
    {
        char buff[1024] = {0};
        int nsize;
        if ((nsize=recv(s,buff,
            sizeof(buff)-1,0))
            !=SOCKET_ERROR)
        {
            std::wstring str = dec.recv_wstring(buff);
            return str;
        }
    }
    return L"";
}



Вот собственно класс дешифрации:

Код

#pragma once

#include "StdAfx.h"
#include <boost/archive/binary_iarchive.hpp>

class Dec
{
public :
    std::vector<std::wstring> recv_vector_wstring(const std::string& buf) {
        std::stringstream is(std::stringstream::in | std::stringstream::out);
        is << buf;
        std::vector<std::wstring> vs;
        boost::archive::binary_iarchive(is) >> vs;
        return vs;
    }

    std::wstring recv_wstring(const std::string& buf) {
        std::stringstream is(std::stringstream::in | std::stringstream::out);
        is << buf;
        std::wstring vs;
        boost::archive::binary_iarchive(is) >> vs;
        return vs;
    }

};


И класс шифрации:

Код

#pragma once 

#include "StdAfx.h"
#include <boost/archive/binary_oarchive.hpp>

class Enc
{
public :
    std::string send_vector_wstring(const std::vector<std::wstring>& vs) {
        std::stringstream os(std::stringstream::in | std::stringstream::out);
        boost::archive::binary_oarchive(os) << vs;
        return os.str();
    }

    std::string send_wstring(std::wstring& vs) {
        std::stringstream os(std::stringstream::in | std::stringstream::out);
        boost::archive::binary_oarchive(os) << vs;
        return os.str();
    }

};


я вот только не пойму... проблемы у меня или это так и задумано чтобы зашифровать и сразу же расшифровать?
PM MAIL   Вверх
boostcoder
Дата 23.11.2010, 22:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(Kirgston @  23.11.2010,  22:20 Найти цитируемый пост)
std::stringstream is(std::stringstream::in | std::stringstream::out);

измените подобные строки на:
Код

std::stringstream os(std::stringstream::in | std::stringstream::out|std::ios::binary);

PM WWW   Вверх
Kirgston
Дата 23.11.2010, 22:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 792
Регистрация: 24.12.2007

Репутация: нет
Всего: 2



Цитата(boostcoder @  23.11.2010,  22:25 Найти цитируемый пост)
измените подобные строки на:

Изменил. Результат такой же.

В файле basic_binary_iarchive.ipp

в коде:

Код

    try {
        std::size_t l;
        this->This()->load(l);
        if(l == std::strlen(BOOST_ARCHIVE_SIGNATURE())) {
            // borland de-allocator fixup
            #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101))
            if(NULL != file_signature.data())
            #endif
                file_signature.resize(l);
            // note breaking a rule here - could be a problem on some platform
            if(0 < l)
                this->This()->load_binary(&(*file_signature.begin()), l);
        }
    }
    catch(archive_exception const &) {  // catch stream_error archive exceptions
        // will cause invalid_signature archive exception to be thrown below
        file_signature = "";   
    }


Срабатывает кэтч. При заходе в this->This()->load(l) . Данная ф-ция должна возвратить указатель на класс Archive. Но при static_cast<Archive *>(this); случается ошибка т.к. this как я понял пустой о_О
PM MAIL   Вверх
boostcoder
Дата 23.11.2010, 22:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(Kirgston @  23.11.2010,  22:20 Найти цитируемый пост)
int ret = send(s, str.c_str(),str.length(), 0);

убедитесь что str.length() == str.size()

Добавлено @ 22:38
Цитата(Kirgston @  23.11.2010,  22:20 Найти цитируемый пост)
если например зашифровать стринг и сразу же расшифровать - всё хорошо. Если же при этом передать по сети шифрованный вариант и попытаться расшифровать то вылетит эксепшен 

собственно это говорит о том, что у вас ошибка в транспорте.

Добавлено @ 22:42
Цитата(boostcoder @  23.11.2010,  22:37 Найти цитируемый пост)
убедитесь что str.length() == str.size()

епс..дурацкая ассоциация осталась от работы с некоторым строковым типом. бред написал smile

Добавлено @ 22:44
что-то я не понял...как вы при приеме определяете сколько нужно прочесть?

Это сообщение отредактировал(а) boostcoder - 23.11.2010, 23:12
PM WWW   Вверх
Kirgston
Дата 23.11.2010, 23:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 792
Регистрация: 24.12.2007

Репутация: нет
Всего: 2



boostcoder, кажется я понял в чем причина... дело в том что после кодирования буфер становится чуток странным. То есть идет какой то символ потом несколько элементов NULL а потом уже сигнатура. 
Вот пример:
user posted image

Собственно это есть как на сервере так и в клиенте. Вот и наверно когда код натыкается на первый NULL сигнатура и откидывается
PM MAIL   Вверх
boostcoder
Дата 24.11.2010, 00:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(Kirgston @  23.11.2010,  23:28 Найти цитируемый пост)
То есть идет какой то символ потом несколько элементов NULL а потом уже сигнатура. 

правильно. вы ведь используете бинарную сериализацию. а в ней не обязаны быть только текстовые данные. чтоб корректно передавать и принимать бинарные массивы, нужно сначала передавать размер этого массива. принимающая сторона считывая этот размер, знает сколько данных нужно причитать следом из сокета.
PM WWW   Вверх
Kirgston
Дата 24.11.2010, 00:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 792
Регистрация: 24.12.2007

Репутация: нет
Всего: 2



В принципе всё уже решил кроме одного... чтобы "состыковать" те же строки или просто бинарные данные можно использовать memcpy. так вот... а есть какой то аналог для std::string? Не хочу просто изобретать муть с динамической памятью . А обычный "+= " и подобные сразу режут строку при первом NULL. 
PM MAIL   Вверх
boostcoder
Дата 24.11.2010, 00:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Код

int len = 
char* buf = 
std::string str;
std::copy(buf, buf+len, std::back_inserter(str));


Добавлено через 1 минуту и 20 секунд
ну или std::string::assign(). зависит от задачи...
PM WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.0590 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.