Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Свой протокол
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Ввод/Вывод, Сеть. Межпроцессное взаимодействие
Румата Эсторский
Здравствуйте, уважаемые разработчики.

Подскажите пожалуйста где можно почитать инфу о создании своего протокола для взаимодействия клиент-серверного приложения. Клиент на Qt, сервер на Java.
Требования к протоколу - компактность и большая скорость обработки пакетов на сервере, так что XML не подходит.

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

И еще скажите - правильно ли сделать такую схему для обработки протокола:
есть базовый класс Message - основные функции по сборке/разборке сообщения, доступ к полям сообщения и т.д.
а дальше для каждого типа сообщения свой класс унаследованный от Message.
Типов сообщений пока около 100, но дальше их будет больше. Скажите, верно ли иметь в программе такую кучу классов для сетевой подсистемы?

kuzulis
А JSON не подходит?
Или вам необходим бинарный протокол?
И что за данные в сообщениях будут передаваться?
Румата Эсторский
Цитата(kuzulis @ 7.2.2011, 17:49) *
А JSON не подходит?
Или вам необходим бинарный протокол?
И что за данные в сообщениях будут передаваться?


Данные - ходы в партиях, списки (игроков, турниров и прочее списки),
бинарные тоже - фотографии, хотя может фотографии заправшивать по HTTP?

я не думал насчет JSON.
Насколько быстро разбирается/собирается JSON?
Какие компонеты для С++ Qt клиента (и для Java сервера) вы порекомендовали бы для работы с JSON?
JSON снимает вопрос насчет наследников от Message или все-таки стоит выстроить такую иерархию независимо от протокола передачи?

crashsp
Цитата(Румата Эсторский @ 7.2.2011, 18:23) *
Цитата(kuzulis @ 7.2.2011, 17:49) *
А JSON не подходит?
Или вам необходим бинарный протокол?
И что за данные в сообщениях будут передаваться?


Данные - ходы в партиях, списки (игроков, турниров и прочее списки),
бинарные тоже - фотографии, хотя может фотографии заправшивать по HTTP?

я не думал насчет JSON.
Насколько быстро разбирается/собирается JSON?
Какие компонеты для С++ Qt клиента (и для Java сервера) вы порекомендовали бы для работы с JSON?
JSON снимает вопрос насчет наследников от Message или все-таки стоит выстроить такую иерархию независимо от протокола передачи?


Ну вот тут нашелся класс для парсения json меня как то раз спас не знаю поможет может чем, а вообще есть отдельная библиотка для работы с json вот только под себя я так и не смог ее адаптировать вот http://qjson.sourceforge.net/

А вот класс:

файл h.

Раскрывающийся текст

/**
* \file json.h
*
* \author Eeli Reilin <eeli@nilier.org>,
*         Mikko Ahonen <mikko.j.ahonen@jyu.fi>
* \version 0.1
* \date 8/25/2010
*/

#ifndef JSON_H
#define JSON_H

#include <QVariant>
#include <QString>

/**
* \enum JsonToken
*/
enum JsonToken
{
    JsonTokenNone = 0,
    JsonTokenCurlyOpen = 1,
    JsonTokenCurlyClose = 2,
    JsonTokenSquaredOpen = 3,
    JsonTokenSquaredClose = 4,
    JsonTokenColon = 5,
    JsonTokenComma = 6,
    JsonTokenString = 7,
    JsonTokenNumber = 8,
    JsonTokenTrue = 9,
    JsonTokenFalse = 10,
    JsonTokenNull = 11
};

/**
* \class Json
* \brief A JSON data parser
*
* Json parses a JSON data into a QVariant hierarchy.
*/
class Json
{
    public:
        /**
         * Parse a JSON string
         *
         * \param json The JSON data
         */
        static QVariant parse(const QString &json);

        /**
         * Parse a JSON string
         *
         * \param json The JSON data
         * \param success The success of the parsing
         */
        static QVariant parse(const QString &json, bool &success);

    private:
        /**
         * Parses a value starting from index
         *
         * \param json The JSON data
         * \param index The start index
         * \param success The success of the parse process
         *
         * \return QVariant The parsed value
         */
        static QVariant parseValue(const QString &json, int &index,
                                   bool &success);

        /**
         * Parses an object starting from index
         *
         * \param json The JSON data
         * \param index The start index
         * \param success The success of the object parse
         *
         * \return QVariant The parsed object map
         */
        static QVariant parseObject(const QString &json, int &index,
                                       bool &success);

        /**
         * Parses an array starting from index
         *
         * \param json The JSON data
         * \param index The starting index
         * \param success The success of the array parse
         *
         * \return QVariant The parsed variant array
         */
        static QVariant parseArray(const QString &json, int &index,
                                       bool &success);

        /**
         * Parses a string starting from index
         *
         * \param json The JSON data
         * \param index The starting index
         * \param success The success of the string parse
         *
         * \return QVariant The parsed string
         */
        static QVariant parseString(const QString &json, int &index,
                                    bool &success);

        /**
         * Parses a number starting from index
         *
         * \param json The JSON data
         * \param index The starting index
         *
         * \return QVariant The parsed number
         */
        static QVariant parseNumber(const QString &json, int &index);

        /**
         * Get the last index of a number starting from index
         *
         * \param json The JSON data
         * \param index The starting index
         *
         * \return The last index of the number
         */
        static int lastIndexOfNumber(const QString &json, int index);

        /**
         * Skip unwanted whitespace symbols starting from index
         *
         * \param json The JSON data
         * \param index The start index
         */
        static void eatWhitespace(const QString &json, int &index);

        /**
         * Check what token lies ahead
         *
         * \param json The JSON data
         * \param index The starting index
         *
         * \return int The upcoming token
         */
        static int lookAhead(const QString &json, int index);

        /**
         * Get the next JSON token
         *
         * \param json The JSON data
         * \param index The starting index
         *
         * \return int The next JSON token
         */
        static int nextToken(const QString &json, int &index);
};

#endif //JSON_H



а вот cpp.
Раскрывающийся текст

/**
* \file json.h
*
* \author Eeli Reilin <eeli@nilier.org>,
*         Mikko Ahonen <mikko.j.ahonen@jyu.fi>
* \version 0.1
* \date 8/25/2010
*/

#include <QDebug>

#include "json.h"

/**
* parse
*/
QVariant Json::parse(const QString &json)
{
    bool success = true;
    return Json::parse(json, success);
}

/**
* parse
*/
QVariant Json::parse(const QString &json, bool &success)
{
    success = true;

    //Return an empty QVariant if the JSON data is either null or empty
    if(!json.isNull() || !json.isEmpty())
    {
        QString data = json;
        //We'll start from index 0
        int index = 0;

        //Parse the first value
        QVariant value = Json::parseValue(data, index, success);

        //Return the parsed value
        return value;
    }
    else
    {
        //Return the empty QVariant
        return QVariant();
    }
}

/**
* parseValue
*/
QVariant Json::parseValue(const QString &json, int &index, bool &success)
{
    //Determine what kind of data we should parse by
    //checking out the upcoming token
    switch(Json::lookAhead(json, index))
    {
        case JsonTokenString:
            return Json::parseString(json, index, success);
        case JsonTokenNumber:
            return Json::parseNumber(json, index);
        case JsonTokenCurlyOpen:
            return Json::parseObject(json, index, success);
        case JsonTokenSquaredOpen:
            return Json::parseArray(json, index, success);
        case JsonTokenTrue:
            Json::nextToken(json, index);
            return QVariant(true);
        case JsonTokenFalse:
            Json::nextToken(json, index);
            return QVariant(false);
        case JsonTokenNull:
            Json::nextToken(json, index);
            return QVariant();
        case JsonTokenNone:
            break;
    }

    //If there were no tokens, flag the failure and return an empty QVariant
    success = false;
    return QVariant();
}

/**
* parseObject
*/
QVariant Json::parseObject(const QString &json, int &index, bool &success)
{
    QVariantMap map;
    int token;

    //Get rid of the whitespace and increment index
    Json::nextToken(json, index);

    //Loop through all of the key/value pairs of the object
    bool done = false;
    while(!done)
    {
        //Get the upcoming token
        token = Json::lookAhead(json, index);

        if(token == JsonTokenNone)
        {
             success = false;
             return QVariantMap();
        }
        else if(token == JsonTokenComma)
        {
            Json::nextToken(json, index);
        }
        else if(token == JsonTokenCurlyClose)
        {
            Json::nextToken(json, index);
            return map;
        }
        else
        {
            //Parse the key/value pair's name
            QString name = Json::parseString(json, index, success).toString();

            if(!success)
            {
                return QVariantMap();
            }

            //Get the next token
            token = Json::nextToken(json, index);

            //If the next token is not a colon, flag the failure
            //return an empty QVariant
            if(token != JsonTokenColon)
            {
                success = false;
                return QVariant(QVariantMap());
            }

            //Parse the key/value pair's value
            QVariant value = Json::parseValue(json, index, success);

            if(!success)
            {
                return QVariantMap();
            }

            //Assign the value to the key in the map
            map[name] = value;
        }
    }

    //Return the map successfully
    return QVariant(map);
}

/**
* parseArray
*/
QVariant Json::parseArray(const QString &json, int &index, bool &success)
{
    QVariantList list;

    Json::nextToken(json, index);

    bool done = false;
    while(!done)
    {
        int token = Json::lookAhead(json, index);

                if(token == JsonTokenNone)
        {
            success = false;
            return QVariantList();
        }
        else if(token == JsonTokenComma)
        {
            Json::nextToken(json, index);
        }
        else if(token == JsonTokenSquaredClose)
        {
            Json::nextToken(json, index);
            break;
        }
        else
        {
            QVariant value = Json::parseValue(json, index, success);

            if(!success)
            {
                return QVariantList();
            }

            list.push_back(value);
                          }
            }

    return QVariant(list);
}

/**
* parseString
*/
QVariant Json::parseString(const QString &json, int &index, bool &success)
{
    QString s;
    QChar c;

    Json::eatWhitespace(json, index);

    c = json[index++];

    bool complete = false;
    while(!complete)
    {
        if(index == json.size())
        {
            break;
        }

        c = json[index++];

        if(c == '\"')
        {
            complete = true;
            break;
        }
        else if(c == '\\')
        {
            if(index == json.size())
            {
                break;
            }

            c = json[index++];

            if(c == '\"')
            {
                s.append('\"');
            }
            else if(c == '\\')
            {
                s.append('\\');
            }
            else if(c == '/')
            {
                s.append('/');
            }
            else if(c == 'b')
            {
                s.append('\b');
            }
            else if(c == 'f')
            {
                s.append('\f');
            }
            else if(c == 'n')
            {
                s.append('\n');
            }
            else if(c == 'r')
            {
                s.append('\r');
            }
            else if(c == 't')
            {
                s.append('\t');
            }
            else if(c == 'u')
            {
                int remainingLength = json.size() - index;

                if(remainingLength >= 4)
                {
                    QString unicodeStr = json.mid(index, 4);

                    int symbol = unicodeStr.toInt(0, 16);
                    
                    s.append(QChar(symbol));

                    index += 4;
                }
                else
                {
                    break;
                }
            }
        }
        else
        {
            s.append(c);
        }
    }

    if(!complete)
    {
        success = false;
        return QVariant();
    }

    return QVariant(s);
}

/**
* parseNumber
*/
QVariant Json::parseNumber(const QString &json, int &index)
{
    Json::eatWhitespace(json, index);

    int lastIndex = Json::lastIndexOfNumber(json, index);
    int charLength = (lastIndex - index) + 1;
    QString numberStr;

    numberStr = json.mid(index, charLength);
    
    index = lastIndex + 1;

    return QVariant(numberStr);
}

/**
* lastIndexOfNumber
*/
int Json::lastIndexOfNumber(const QString &json, int index)
{
    int lastIndex;

    for(lastIndex = index; lastIndex < json.size(); lastIndex++)
    {
        if(QString("0123456789+-.eE").indexOf(json[lastIndex]) == -1)
        {
            break;
        }
    }

    return lastIndex -1;
}

/**
* eatWhitespace
*/
void Json::eatWhitespace(const QString &json, int &index)
{
    for(; index < json.size(); index++)
    {
        if(QString(" \t\n\r").indexOf(json[index]) == -1)
        {
            break;
        }
    }
}

/**
* lookAhead
*/
int Json::lookAhead(const QString &json, int index)
{
    int saveIndex = index;
    return Json::nextToken(json, saveIndex);
}

/**
* nextToken
*/
int Json::nextToken(const QString &json, int &index)
{
    Json::eatWhitespace(json, index);

    if(index == json.size())
    {
        return JsonTokenNone;
    }

    QChar c = json[index];
    index++;
    switch(c.toAscii())
    {
        case '{': return JsonTokenCurlyOpen;
        case '}': return JsonTokenCurlyClose;
        case '[': return JsonTokenSquaredOpen;
        case ']': return JsonTokenSquaredClose;
        case ',': return JsonTokenComma;
        case '"': return JsonTokenString;
        case '0': case '1': case '2': case '3': case '4':
        case '5': case '6': case '7': case '8': case '9':
        case '-': return JsonTokenNumber;
        case ':': return JsonTokenColon;
    }

    index--;

    int remainingLength = json.size() - index;

    //True
    if(remainingLength >= 4)
    {
        if (json[index] == 't' && json[index + 1] == 'r' &&
            json[index + 2] == 'u' && json[index + 3] == 'e')
        {
            index += 4;
            return JsonTokenTrue;
        }
    }

    //False
    if (remainingLength >= 5)
    {
        if (json[index] == 'f' && json[index + 1] == 'a' &&
            json[index + 2] == 'l' && json[index + 3] == 's' &&
            json[index + 4] == 'e')
        {
            index += 5;
            return JsonTokenFalse;
        }
    }

    //Null
    if (remainingLength >= 4)
    {
        if (json[index] == 'n' && json[index + 1] == 'u' &&
            json[index + 2] == 'l' && json[index + 3] == 'l')
        {
            index += 4;
            return JsonTokenNull;
        }
    }

    return JsonTokenNone;
}


Румата Эсторский
Я вот думаю не воспользоваться ли QHessian http://habrahabr.ru/blogs/cpp/109393/
Он бинарный, то есть компактнее JSON, и на первый взгляд очень удобный.
Как считаете?
crashsp
Цитата(Румата Эсторский @ 10.2.2011, 2:33) *
Я вот думаю не воспользоваться ли QHessian http://habrahabr.ru/blogs/cpp/109393/
Он бинарный, то есть компактнее JSON, и на первый взгляд очень удобный.
Как считаете?


По моему отличный вариант плюсов много )) да и на первый взгляд реализовано все на уровне... НО я сам вижу ее в первый раз так что если под вашу задачу подходит почему бы нет ??

ПЖЛ не бросайте тему если вдруг на чем то конкретном остановитесь отпишитесь
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.