отправка структуры через сокет;сервер и клиент на одной машине - PullRequest
2 голосов
/ 31 августа 2010

Мой сервер и клиент работают на одной машине, поэтому у меня нет проблем с порядком байтов и т. Д. Мне нужно что-то, что работает как на vc ++, так и на g ++ и, возможно, самый простой способ. Чем я могу отправить структуру?

Редактировать

struct Info
{
     int**   fields; 
     char**  field_names;
};

Ответы [ 4 ]

1 голос
/ 31 августа 2010

Посмотрите на Boost.Serialization , вот довольно тривиальный пример, который я разместил в другой вопрос

#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/string.hpp>

#include <string>

struct Message
{
    std::string _a;
    std::string _b;

    template <class Archive>
    void serialize(
            Archive& ar,
            unsigned int version
            )
    {
        ar & _a;
        ar & _b;
    }
};

int
main()
{
    Message msg;
    msg._a = "hello";
    msg._b = "world";
    std::ostringstream os;
    boost::archive::text_oarchive ar( os );
    ar & msg;
}

Обратите внимание, что у библиотеки сериализации НАМНОГО больше возможностей, чем у этой. Он может сериализовать указатели, ссылки, контейнеры и многие объекты в других библиотеках Boost. Мой пример здесь показывает навязчивую сериализацию, если вы не можете изменить свою структуру, есть способы сериализации также не навязчиво .

0 голосов
/ 31 августа 2010

Вы можете объявить статический символ без знака следующим образом:

#define MSGBUFSIZE  512
static unsigned char ClientSendBuf[MSGBUFSIZE];

, а затем скопировать вашу структуру в массив следующим образом:

memmove(&ClientSendBuf[2], &struct, sizeof(struct));

теперь это там, где это зависит от реализации.Я использую Borland C ++, поэтому моя отправка действует следующим образом:

ClientSocket->Socket->SendBuf(ClientSendBuf, ClientSendBuf[0]+CRC16SIZE);

Причина, по которой я использую ClientSendBuf [0], заключается в том, что размер моего сообщения хранится в ClientSendBuf [0] примерно так:

ClientSendBuf[0] = 4 + sizeof(struct);             //Byte Count

(Примечание. Замените struct на имя вашего struct)

Я также добавляю проверку CRC в конец моего сообщения следующим образом:

#define CRC16SIZE   2

...

cs = CheckSum((unsigned char *)ClientSendBuf, ClientSendBuf[0]);
    memmove(&ClientSendBuf[ClientSendBuf[0]], &cs, CRC16SIZE);

...

unsigned short __fastcall TFormMenu::CheckSum(unsigned char *p, int length)
{
    int i;

    for (cs = 0, i = 0; i < length; i++) {
        cs += p[i];
    }
    return cs;
}

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

Все это предполагает, что у вас есть структура POD.Часть static не нужна, но как я это сделал в своем конкретном приложении.Я также замутил некоторые детали.Пишите в комментариях, если у вас есть вопросы.YMMV.

0 голосов
/ 31 августа 2010

У вашей структуры есть указатели на данные, а не на сами данные. Если вы должны использовать типы POD (то есть int и char []) в структуре, то это может быть отправлено непосредственно в сокет.

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

boost :: asio содержит несколько очень простых примеров, которые вы можете использовать.

0 голосов
/ 31 августа 2010

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

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

Допустим, у вас есть такая структура:

struct DataStruct
{
   int x;
   char* message;
   short messageLen;
}

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

Целые числа - 4 байта в G ++ и VC ++;оба символа - 1 байт;шорты по 2 байта.

Сначала передайте значение x, затем messageLen var и используйте эту переменную, чтобы создать переменный размер буфера на другой стороне.Затем вы можете записать данные сообщения в символ *.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...