Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Передача объекта через сокет

Модерирует : ShIvADeSt

 Версия для печати • ПодписатьсяДобавить в закладки
Страницы: 1 2

Открыть новую тему     Написать ответ в эту тему

KADABRA



Великий покусатель
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Вот пример классов:
 
class CBase
{
private:
   int m_iClassType;
   unsigned int m_uiSomeData;
   long double m_ldMoreData;
public:
   CBase(UINT uiSomeData, long double MoreData);
   virtual ~CBase();
   int GetClassType();
   int GetSomeData();
   long double GetMoreData();
};
class CMyClass : public CBase
{
private:
   int m_iStrLen;
   char * m_pStr;
   double m_dSomeData;
public:
   CMyClass(char * str, double data);
    virtual ~CMyClass();
    const char * GetStr();
};
 
Как передать их при помощи CAsyncSocket и принять на другом компе в зависимости от того, какой это объект - CBase или CMyClass, создать новый объект соответствующего класса и записать все полученные данные в него.

----------
Это не подпись.

Всего записей: 1718 | Зарегистр. 14-07-2003 | Отправлено: 11:45 04-06-2004 | Исправлено: KADABRA, 11:53 04-06-2004
redp

Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
э
если ты хочешь именно объекты передавать прозрачно по сетке, то тебе копать в сторону CORBA или RPC надо
там все гораздо сложнее чем ты думаешь, в частности возникает такое неприятное явление как marshalling

----------
помни - ты с потрохами принадлежишь государству

Всего записей: 514 | Зарегистр. 16-06-2003 | Отправлено: 11:52 04-06-2004
WiseAlex



Софтовых дел М...
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
есть в mfc по-моему cfilesocket он поддерживает передачу файлов, а тебе остается реализовать сериализацию классов (перекрыть Serial и объявить IMPLEMENT_SERIAL и DECLARE_SERIAL в cpp и h файле)
более подробно http://www.rsdn.ru/article/mfc/mfcseria.xml

Всего записей: 1001 | Зарегистр. 02-03-2003 | Отправлено: 12:01 04-06-2004
KADABRA



Великий покусатель
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
redp
А проще как-то можно?
И возникла такая идея:
берём и создаём массив char[], такой длинны, как размер всех переменнях
   int m_iClassType;
   unsigned int m_uiSomeData;
   long double m_ldMoreData;
+
    int m_iStrLen;
   strlen m_pStr; // !!!!!!!!!!!
   double m_dSomeData;
и по очереди туда всё заносим (но как не знаю ), просто передаём сначала длинну строки (не обязательно), потом её саму, считываем первые 4 байта и преобразуем в int и в зависимости от него создаём новый нужный объект и передаём ему. Он по очереди считывает данные m_iClassType m_uiSomeData m_ldMoreData int m_iStrLen, создаёт строку такой длинны, и считывает туда из строки столько байтов, m_dSomeData.
Но как это реализовать не знаю, знаю как только с бинарными файлами такое делать.

----------
Это не подпись.

Всего записей: 1718 | Зарегистр. 14-07-2003 | Отправлено: 12:17 04-06-2004
fuxx

Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Чего вы пугаете человека?
В таком простом случае (когда так мало классов) самое простое - добавить в CBase  
абстрактные методы Dump( Stream& )/Restore ( Stream& ) а в каждом наследованном  
переопределять их. Тогда определение Dump(псевдокод) будет таким (перед ним кто-то
сохранил в Stream наш ClassID):
 
char buf[BUFSZ];
 
sprintf ( buf, "%d %ud %ld\n", this->GetClassID (),  
this->m_iClassType,  
this->m_uiSomeData,  
this->m_ldModeData );
 
Stream << buf;
 
Restore (кто-то уже позаботился о ClassID):
 
char buf[BUFSZ];
 
Stream.getline ( buf, BUFSZ );
 
sscanf ( buf, "%d %ud %ld\n",  
&this->m_iClassType,  
&this->m_uiSomeData,  
&this->m_ldModeData );
 
ну и то кто заботиться о ClassID:
 
Restore ( Stream )
{
int classid;
char buf[BUFSZ];
 
Stream.getline (buf, BUFSZ)
sscanf ( buf, "%d\n", &classid );
if ( classid == CMyClass::GetClassID () )
{
 CMyClass Ret = new CMyClass;
 REt->Restore ( Stream );
 
return Ret;
} else if ( classid == CAnotherClass::GetClassID () )
{
CAnotherClass *Ret = new CAnotherClass
Ret->Restore ( Stream );
return Ret;
}
}

Всего записей: 117 | Зарегистр. 14-04-2003 | Отправлено: 12:22 04-06-2004
KADABRA



Великий покусатель
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
WiseAlex

Цитата:
есть в mfc по-моему cfilesocket он поддерживает передачу файлов, а тебе остается реализовать сериализацию классов (перекрыть Serial и объявить IMPLEMENT_SERIAL и DECLARE_SERIAL в cpp и h файле)
более подробно http://www.rsdn.ru/article/mfc/mfcseria.xml  
 

Но тогда, на сколько я помю, CData должен быть родственным от СObject, а не будут-ли передаватся все переленные СObject'а?
А где есть инфа по СSocketFile по русски?

----------
Это не подпись.

Всего записей: 1718 | Зарегистр. 14-07-2003 | Отправлено: 12:25 04-06-2004
redp

Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
fuxx
я не пугаю
во первых по условиям задачи далеко не факт, что машина отправитель и машина получатель имеют одинаковую архитектуру (например порядок байт в слове)
во вторых твой способ имеет недостаток - при переводе dword в строку тебе нужно передавать больше байт, чем при передаче просто dword. Соотв-но если приложение будет передавать такие объекты пачками - сетка может и тово...

----------
помни - ты с потрохами принадлежишь государству

Всего записей: 514 | Зарегистр. 16-06-2003 | Отправлено: 12:27 04-06-2004
KADABRA



Великий покусатель
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Цитата:
Сервер нужен лишь для хранения контакт-листов и IP-адресов. После инициализации коннекта к серверу, общение с другими пользователями идет напрямую через TCP-протокол, что очень сильно снижает нагрузку на сервер.
Из этого мы имеем два протокола общения. А придумывать особо ничего не надо. Можно просто создать классы сообщений, сериализовать их в XML, упаковать ZIP-ом (вроде даже есть какие-то классы для этого), и отсылать. А по пришествии ответа делать обратную процедуру, благо в .NET все это просто. Хотя боюсь, что используя .NET будет невысокая производительность - мы у себя все писали на C++.

 
Вот тут надыбал: http://www.rsdn.ru/Forum/Message.aspx?mid=659947#659947
 
А как сериализовать в XML?
 
Добавлено

Цитата:
А как сериализовать в XML?

Хотя это мне не поможет.
А как на счёт записи всего в строку ( как реализовать???), как в двоичный файл(чем-то напоминает сериализацию)

----------
Это не подпись.

Всего записей: 1718 | Зарегистр. 14-07-2003 | Отправлено: 13:00 04-06-2004
UncoNNecteD



Silver Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
KADABRA
Твоя идея правильна. Сначала передаешь код определяющий какого типа этот объект, а потом в соответствии с разработанным форматом передаешь последовательно все поля объекта.

----------
-= Я тут чертовски давно =-

Всего записей: 4040 | Зарегистр. 21-03-2002 | Отправлено: 14:55 04-06-2004
fuxx

Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору

Цитата:
во вторых твой способ имеет недостаток - при переводе dword в строку тебе нужно передавать больше байт, чем при передаче просто dword. Соотв-но если приложение будет передавать такие объекты пачками - сетка может и тово...

 
Этим недостатком страдают многие прикладные протоколы интернета (например  
SMTP/POP/HTTP). Но вот интернет вполне себе функционирует. Просто достоинства
перевешивают недостатки.
 

Цитата:
А как на счёт записи всего в строку ( как реализовать???), как в двоичный файл(чем-то напоминает сериализацию)

 
Я ж тебе написал. Посмотри мой пример.

Всего записей: 117 | Зарегистр. 14-04-2003 | Отправлено: 19:25 04-06-2004
KADABRA



Великий покусатель
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
fuxx
А где есть описание printf() и sprintf() ?
И такой код:
 sprintf ( buf, "%d %ud %ld\n", this->GetClassID (),  
this->m_iClassType, ...
не преобразует m_iClassType в строку?
То-есть мне нужно так: если int занимает 4 байта, то он должен занимать в этой строке 4 байта - копия int'а, а не представление его строкой.

----------
Это не подпись.

Всего записей: 1718 | Зарегистр. 14-07-2003 | Отправлено: 11:16 05-06-2004
fuxx

Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору

Цитата:
А где есть описание printf() и sprintf() ?  

Ты издеваешься?!

Всего записей: 117 | Зарегистр. 14-04-2003 | Отправлено: 20:46 05-06-2004
WiseAlex



Софтовых дел М...
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
KADABRA

Цитата:
Но тогда, на сколько я помю, CData должен быть родственным от СObject, а не будут-ли передаватся все переленные СObject'а?

ты прав будут и наследование от  CObject нужно

Цитата:
А где есть инфа по СSocketFile по русски?

кроме msdn вроде нигде..., если только добрые люди не переведут. глянь подробнее на http://www.rsdn.ru  они иногда что-то переводят

Всего записей: 1001 | Зарегистр. 02-03-2003 | Отправлено: 12:19 07-06-2004
KADABRA



Великий покусатель
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
fuxx

Цитата:
Ты издеваешься?!

Нет, просто я никогда не использовал эти функции, вместо printf() - объект cout.
WiseAlex

Цитата:
глянь подробнее на http://www.rsdn.ru  

Нету там, но я решил по-своему, но одна проблема осталась. Вот пример без объектов:

Код:
 
#include <iostream>
#include <Windows.h>
using namespace std;
 
typedef unsigned char BYTE;
 
int main()
{
int iLen;
 
int a = 436;
unsigned int b =5445644;
long as = -345346345;
 
int iStrLen;
char c[] = "asdf  _ ~&* ds & SOME StRiNg";
iStrLen = strlen(c);
 
iLen = (sizeof a) + (sizeof b) + (sizeof as) + (sizeof iStrLen) + iStrLen;
 
BYTE * buf = new BYTE[iLen];
 
int i = 0;
     
memcpy(&buf[i], &a, sizeof a);
i = i + sizeof a;
memcpy(&buf[i], &b, sizeof b);
i = i + sizeof b;
memcpy(&buf[i], &as, sizeof as);
i = i + sizeof as;
memcpy(&buf[i], &iStrLen, sizeof iStrLen);
i = i + sizeof iStrLen;
memcpy(&buf[i], &c, iStrLen);
i = i + iStrLen;
 
cout << a << ' ' << b << ' ' << as << ' ' << iStrLen << ' ' << c << ' ' << i;
 
a = b = as = iStrLen = 0;
i = 0;
 
cout << "\n\n\n000\n\n\n";
 
memcpy(&a, &buf[i], sizeof a);
i = i + sizeof a;
memcpy(&b, &buf[i], sizeof b);
i = i + sizeof b;
memcpy(&as, &buf[i], sizeof b);
i = i + sizeof as;
memcpy(&iStrLen, &buf[i], sizeof iStrLen);
i = i + sizeof iStrLen;
char * str = new char[iStrLen + 1];
memcpy(str, &buf[i], iStrLen);
i = i + iStrLen;
str[iStrLen] = '\0';
 
cout << a << ' ' << b << ' ' << as << ' ' << iStrLen << ' ' << str << ' ' << i;
cin.get();
}
 

 
Но русские буквы в строке не проходят :(
Надо наверно как-то Unicode прикрутить?

----------
Это не подпись.

Всего записей: 1718 | Зарегистр. 14-07-2003 | Отправлено: 12:13 08-06-2004
WiseAlex



Софтовых дел М...
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
KADABRA

Цитата:
Но русские буквы в строке не проходят

Приложение консольное - используй ansitooem(с названием может ошибся, но не слишком)
--------
Твое решение будет работать, но
1) класс не должен содержать данных, использующих динамическое выделение памяти (строки например) и других данных-указателей
2)объекты к моменту чтения уже должны бать созданы
3)последовательность и количество склассов должно совпадать
4)(следует из 1) - т.к. классы содержат виртуальные функции нужно пропускать указатель на таблице виртуальных функций.(первые 4байта)
5)Слишком конкретная реализация не позволит обобщить
6)Здесь дополнят более сведущие люди
--------
в любом случае обобщение ведет к созданию своей фабрики классов

Всего записей: 1001 | Зарегистр. 02-03-2003 | Отправлено: 16:30 08-06-2004
fuxx

Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
KADABRA
Как было верно замечено в одном из предыдущих постов redp твой код не будет работать если общающиеся с его помощью машины имеют разные архитектуры, например Windows 32 бит и Windows 64 бит. Но насколько я понимаю для тебя это не проблема.
 
printf sprintf это функции которые используются чаще в Си чем в С++.
 
Паскалевский стиль работы с адресами элементов массива выглядит немного угловато.
Попробуй так:  
Сохранение:

Код:
 
BYTE* p = buf;
 
memcpy ( p, &var, sizeof ( var-type ) );
  p += sizeof ( var-type );
memcpy ( p, &var2, sizeof ( var2-type ) );
  p += sizeof ( var2-type );
....
 

 
Восстановление:

Код:
 
BYTE* p = buf;
 
memcpy ( &var, p, sizeof ( var-type ) );
  p += sizeof ( var-type );
memcpy ( &var2, p, sizeof ( var-type ) );
  p += sizeof ( var2-type );
...
 

 

Цитата:
1) класс не должен содержать данных, использующих динамическое выделение памяти (строки например) и других данных-указателей
4)(следует из 1) - т.к. классы содержат виртуальные функции нужно пропускать указатель на таблице виртуальных функций.(первые 4байта)  

Плохой совет сохранять структуры и объекты простым копированием байт. Ведь бывает еще выравнивание структур (и объектов) по разным адресам. Это когда компилятор вставляет между членами класса пустое пространство, чтобы каждый член класса начинался с четного адреса.
 
Так что не стоит таким образом сохранять сами объекты. Т.е. код вроде такого например плох тем что строка "c" не будет сохранена, а на противоположной стороне ты получишь ошибку работы с памятью:

Код:
 
class CClass
{
virtual void GetC () const { return c; }
char* c;
};
 
CClass a;
 
memcpy ( buf, &a, sizeof ( CClass ) );
 
 

 
Указатель a.c совершенно бессмысленный в адресном пространстве другого процесса. Его нужно сохранять как строку символов а не как указатель. Т.е как ты и делал:

Код:
 
 iStrLen = strlen(c);
  memcpy(&buf[i], &c, iStrLen);
  i = i + iStrLen;  
 

 
Сохраняй только базовые типы данных из которых состоят члены класса.
 

Цитата:
обобщение ведет к созданию своей фабрики классов

Точно.
 
Т.е. если подытожить тред, для каждого сериализуемого объекта тебе нужно писать в поток (буфер)  
 
1. Идентификатор уникально выделяющий класс этого объекта среди всех сериализуемых классов чтобы на противоположной стороне его можно было правильно восстановить.
2. Все простые члены класса, необходимые для правильного восстановления объекта на другой стороне, в виде потока байт. При этом для указателей пишется не сам указатель а то на что он указывает. Если объект содержит объект то вложенный также нужно сохранять разбивая на простые части.
 
Для каждого класса обе эти операции отличаются плюс класс вроде бы должен скрывать свою структуру (см. ООП), значит самое правильное место для размещения функций идентификатора класса и сохранения это сам сохраняемый класс. Проще всего это сделать, если завести для сериализуемых объектов базовый класс, в котором определить абстрактные методы GetID (), GetObjectSize () / Dump () / Restore (). А каждый класс, который хочет сериализоваться наследуется от него и по своему определяет  эти методы.
 
Затем ты заводишь класс-фабрику которая сохраняет и восстанавливает твои объекты из потока. Ее задача при сохранении объекта в поток - (если ты пользуешься буфером перед отправкой в поток а не пишешь в него напрямую) запросить у объекта размер, выделить буфер, затем вызвать у объекта Dump, после чего число байт равное размеру объекта из буфера можно отправлять в поток. В случае восстановления объекта фабрика читает из потока идентификатор класса которому принадлежит объект, создает "пустой" объект такого класса и вызывает у него Restore с буфером ( или прямо с потоком).

Всего записей: 117 | Зарегистр. 14-04-2003 | Отправлено: 17:58 08-06-2004
KADABRA



Великий покусатель
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
WiseAlex

Цитата:
Твое решение будет работать, но
1) класс не должен содержать данных, использующих динамическое выделение памяти (строки например) и других данных-указателей
2)объекты к моменту чтения уже должны бать созданы
3)последовательность и количество склассов должно совпадать
4)(следует из 1) - т.к. классы содержат виртуальные функции нужно пропускать указатель на таблице виртуальных функций.(первые 4байта)
5)Слишком конкретная реализация не позволит обобщить  

 
1)ПочемУ?
2)Да.
3)??? Не понял :?
4):1)
5) Это как?
 
fuxx

Цитата:
Windows 32 бит и Windows 64 бит

В данный момент этот вопрс не так важен, но надо запомнить :)
 
Предыдущий код представлен как решение записи в строку объекта.
В данный момент код выгледит так:

Код:
 
// CSData.h: header file of CSData class
 
#pragma once
 
#include "Consts.h" //Константы
#include "../SSocket30s.h"
 
// Базовый класс CSData
 
//#ifndef _CSDATA_H_
//#define _CSDATA_H_
 
class CSData
{
public:
// enum { iSendCount = 6 };
UINT m_uiCVer; //Версия обекта
 
CSData(const int * piTo = NULL, int iToCount = 0, UINT uiType = OT_NULL);
CSData(const CSData & csdSet);
virtual ~CSData();
 
UINT GetObjType(); //Возвращает тип объекта
UINT GetOpt();
 
int GetDestCount();
int GetDestID(int iCount);
const int * GetDestID();
 
void SetFromID(UINT uiFrom);
UINT GetFromID();
 
 
virtual int GetSendLen();
 
virtual BYTE * ToSend();
virtual int ToRecive(IN BYTE * pRecvStr, IN const int * iRecvLen);
 


// int GetOpt(CSDataOpt setOpt);

private:
//////////// External
UINT m_uiObjType; //Тип объекта
int m_iDestCount; //количество точек назначения
int * m_piDestID; //ID клиента/сервера - точка назначения
UINT m_uiFromID; //ID клиента/сервера - от кого
UINT m_uiOptions; //Дополнитнльные опции
//
//
///////////// Internal
BYTE * m_pBuf;
};
//#endif
 

Функция записи в строку:

Код:
 
BYTE * CSData::ToSend()
{
if(m_pBuf)
delete [] m_pBuf;
int * iBufLen = new int;
*iBufLen = (sizeof m_uiObjType) + (sizeof m_uiCVer) + (sizeof m_iDestCount) +
(m_iDestCount * sizeof (int)) + (sizeof m_uiFromID) + (sizeof m_uiOptions);
m_pBuf = new BYTE[*iBufLen];
 
int iPos = 0;
memcpy(&m_pBuf[iPos], &m_uiObjType, sizeof m_uiObjType); // 1
iPos = iPos + sizeof m_uiObjType;
 
memcpy(&m_pBuf[iPos], &m_uiCVer, sizeof m_uiCVer); // 2
iPos = iPos + sizeof m_uiCVer;
 
memcpy(&m_pBuf[iPos], &m_iDestCount, m_iDestCount); // 3
iPos = iPos + sizeof m_iDestCount;
 
memcpy(&m_pBuf[iPos], m_piDestID, m_iDestCount * (sizeof (int))); // 4
iPos = iPos + (m_iDestCount * (sizeof (int)));
 
memcpy(&m_pBuf[iPos], &m_uiFromID, sizeof m_uiFromID); // 5
iPos = iPos + sizeof m_uiFromID;
 
memcpy(&m_pBuf[iPos], &m_uiOptions, sizeof m_uiOptions); // 6
iPos = iPos + sizeof m_uiOptions;
 
return m_pBuf;
}
 

А вот на счёт

Цитата:
 Затем ты заводишь класс-фабрику которая сохраняет и восстанавливает твои объекты из потока. Ее задача при сохранении объекта в поток - (если ты пользуешься буфером перед отправкой в поток а не пишешь в него напрямую) запросить у объекта размер, выделить буфер, затем вызвать у объекта Dump, после чего число байт равное размеру объекта из буфера можно отправлять в поток. В случае восстановления объекта фабрика читает из потока идентификатор класса которому принадлежит объект, создает "пустой" объект такого класса и вызывает у него Restore с буфером ( или прямо с потоком).  

Мы принимаем строку (вне этого объекта, и в зависимости от первых 4 байт создаём нужный объект (это только базовый класс):

Код:
 
CSData * pObj = NULL;
UINT ObjType;
memcpy(&RecivedString, &ObjType, sizeof ObjType);
switch(ObjType)
{
case OT_NULL:
pObj = new CSData;
cCSData.ToRecive(RecivedString, RecivedLen);
break;
case OT_STRING:
...
}
 


Цитата:
 Затем ты заводишь класс-фабрику которая сохраняет и восстанавливает твои объекты из потока

Подробней пожалуйсто :)
И как с русским в строке?

----------
Это не подпись.

Всего записей: 1718 | Зарегистр. 14-07-2003 | Отправлено: 19:32 08-06-2004
WiseAlex



Софтовых дел М...
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
KADABRA
Чтобы зря воду не лить:
 
Цитата:
1)ПочемУ?  

указатель ссылается на данный, а при копировании указателя в другой комп на что он будет ссылаться?
Читай книги(извини за возможный снобизм ответа, но без этого никак).
---
Ты фактически создал свой класс-предок для реализации сериализации, которая уже есть в mfc а зачем? бери готовое решение и не мучайся - будут работать и строки и все стальное. Специально посмотрел размер объекта CObject и убедился - он не содержит внутренних данных, поэтому размер 4байта(только указатель на vtable)
--
в любом случай вариант с memcpy - не лучшее решение

Всего записей: 1001 | Зарегистр. 02-03-2003 | Отправлено: 09:38 09-06-2004
KADABRA



Великий покусатель
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
WiseAlex

Цитата:
указатель ссылается на данный, а при копировании указателя в другой комп на что он будет ссылаться?
Читай книги(извини за возможный снобизм ответа, но без этого никак).  

Так я же не копирую объект целиком, а по частям, потому и спрашиваю, почему в моём случае этого не будет.

Цитата:
сериализации, которая уже есть в mfc а зачем? бери готовое решение и не мучайся

Своё всегда прятней . И работает.
 
Добавлено
А вот и русские буквы в строке логут быть:

Код:
 
#include <iostream>
#include <Windows.h>
using namespace std;
 
typedef unsigned char BYTE;
 
int main()
{
int iLen;
 
int a = 436;
unsigned int b =5445644;
long as = -345346345;
 
int iStrLen;
wchar_t c[39];
wcin.getline(c, 38);
// wcscpy(c, ("asdf  _ ~&* ds"));
iStrLen = wcslen(c);
 
iLen = (sizeof a) + (sizeof b) + (sizeof as) + (sizeof iStrLen) + iStrLen * sizeof (wchar_t);
 
BYTE * buf = new BYTE[iLen];
 
int i = 0;
     
memcpy(&buf[i], &a, sizeof a);
i = i + sizeof a;
memcpy(&buf[i], &b, sizeof b);
i = i + sizeof b;
memcpy(&buf[i], &as, sizeof as);
i = i + sizeof as;
memcpy(&buf[i], &iStrLen, sizeof iStrLen);
i = i + sizeof iStrLen;
memcpy(&buf[i], &c, iStrLen * sizeof (wchar_t));
i = i + iStrLen * sizeof (wchar_t);
 
wcout << a << ' ' << b << ' ' << as << ' ' << iStrLen << ' ' << c << ' ' << i;
 
a = b = as = iStrLen = 0;
i = 0;
 
cout << "\n\n\n000\n\n\n";
 
memcpy(&a, &buf[i], sizeof a);
i = i + sizeof a;
memcpy(&b, &buf[i], sizeof b);
i = i + sizeof b;
memcpy(&as, &buf[i], sizeof b);
i = i + sizeof as;
memcpy(&iStrLen, &buf[i], sizeof iStrLen);
i = i + sizeof iStrLen;
wchar_t * str = new wchar_t[iStrLen + 1];
memcpy(str, &buf[i], iStrLen * sizeof (wchar_t));
i = i + iStrLen * sizeof (wchar_t);
 
str[iStrLen] = '\0';
 
wcout << a << ' ' << b << ' ' << as << ' ' << iStrLen << ' ' << str << ' ' << i;
 
cin.get();
cin.get();
}
 


----------
Это не подпись.

Всего записей: 1718 | Зарегистр. 14-07-2003 | Отправлено: 10:00 09-06-2004
KADABRA



Великий покусатель
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Всё. Объект записан в строку и успешно восстановлен. Благодаря memcpy().
Вопрос закрыт.

Всего записей: 1718 | Зарегистр. 14-07-2003 | Отправлено: 09:58 13-06-2004
Открыть новую тему     Написать ответ в эту тему

Страницы: 1 2

Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Передача объекта через сокет


Реклама на форуме Ru.Board.

Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
Modified by Ru.B0ard
© Ru.B0ard 2000-2024

BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

Рейтинг.ru