Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Сети > протокол передачи данных


Автор: azesmcar 17.3.2009, 15:11
Добрый день,

Нужно разработать протокол коммуникации клиент-серверного приложения.
отправлятся будут как текстовые так и бинарные сообщения, размышляю над несколькими вариантами решения
1. Разделить сообщения на 2 типа, текстовое и бинарное, отправлять в заголовке флаг для типа сообщения
2. Отправлять всегда текстовое и делать преобразование при отправлении/получении

недостатки 1 метода
сервер кросс-платформенный и возможна проблема в будущем с big-endian, little-endian, так как клиент не знает на чем стоит сервер, а сервер не знает на чем стоит клиент. Можно обменятся этими данными, но тогда замучаюсь с преобразованиями.

недостатки 2 метода
перегружается сервер лишними конвертациями и парсингом, производительность сервера - критический параметр. К тому же увеличивается протокол обмена данными. т.е. в первом случае чтоб отправить число 25 - хватит 1 байта, во втором нужно 3 (2 байта для текста, 1 для сепаратора).

Есть идеи как можно красиво и без потерь реализовать кроссплатформенный протокол? В принципе обработчики тесктовых и бинарных совершенно разные, текстовые обрабатывает сервер, бинарные отдает плагинам в DLL. Такое разделение возможно придаст немного гибкости решению.

Заранее спасибо

Автор: GrayCardinal 17.3.2009, 15:36
ИМХО. если
Цитата

производительность сервера - критический параметр

речи о конвертации бинарных данных в текстовые и обратно речи быть не может. 
Цитата

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

Не вижу проблемы...

Автор: azesmcar 17.3.2009, 15:56
Цитата

Не вижу проблемы... 


получаем заголовок сообщения, проверяем тип сообщения, получаем остальное.
клиент при подключении отправляет цифру - 1 к примеру, смотрим равно ли то что отправил клиент 1 или нет, если равно значит ничего переворачивать не надо, если нет - значит переворачиваем. Получаю
Код

union
{
    int i;
    short[2] j;
    char[4] k;
}

тогда надо ковертировать и short и int, еще теоретически возможна разница в размерах int на сервере и клиенте..тогда вообще непоятно что получается, да и код немного нечитабельный выйдет.  smile 

Автор: Lazin 17.3.2009, 16:16
просто ты принимаешь за данность, что у тебя все бинарные данные в твоем протоколе имеют определенный endianess, на тех платформах, на которых оно совпадает с endianess платформы - ничего не делаешь, та нех, на которых не совпадает - преобразуешь...
зы 
я бы посмотрел в сторону http://code.google.com/apis/protocolbuffers/

Автор: azesmcar 17.3.2009, 16:29
Цитата

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


можно и так, но тогда и клиенту придется конвертировать в случае чего, хотя это не так уж важно, а что делать с размерами int? 
Цитата

я бы посмотрел в сторону protocol buffers 


Посмотрел, немного помучаю сегодня, но не думаю что это вариант..по любому это конвертация из бинарных в текстовые и обратно..а это замедлит процесс обработки сообщений..

Автор: Lazin 17.3.2009, 16:44
Цитата(azesmcar @  17.3.2009,  16:29 Найти цитируемый пост)
Посмотрел, немного помучаю сегодня, но не думаю что это вариант..по любому это конвертация из бинарных в текстовые и обратно..а это замедлит процесс обработки сообщений.. 

нет там никакой конвертации

Цитата(azesmcar @  17.3.2009,  16:29 Найти цитируемый пост)
можно и так, но тогда и клиенту придется конвертировать в случае чего, хотя это не так уж важно, а что делать с размерами int?

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

Автор: azesmcar 18.3.2009, 15:15
Цитата

нет там никакой конвертации


вчера не смог, интернет отключили..сегодня дома посмотрю поподробнее.
Цитата

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


например как? мне нужен int (т.е. 32 бита) для какого типа данных С++ гарантирует 32 бита?

Автор: GrayCardinal 18.3.2009, 15:18
azesmcar, 
Да вроде Си гарантирует int - 32 бита smile  

Автор: azesmcar 18.3.2009, 15:25
Цитата

Да вроде Си гарантирует int - 32 бита


Если я правильно помню стандарт гарантирует
short<=int<=long
но точной гарантии на размер он однозначно не дает

Добавлено @ 15:29
в принципе скорость работы сервера критична, но не настолько чтоб отбросить этот вариант как совсем невероятный. Если это придаст красоту решению и не очень сильно воздействует на скорость работы - можно..но не желательно  smile 

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

Код

int to_int(const std::string& t) {
    int length    = t.length();
    int temp    = length;
    int result    = 0;
    
    switch (temp) {
        case 10:    result += 1000000000 * (t[length - temp--] - 48);
        case 9:        result += 100000000 * (t[length - temp--] - 48);
        case 8:        result += 10000000 * (t[length - temp--] - 48);
        case 7:        result += 1000000 * (t[length - temp--] - 48);
        case 6:        result += 100000 * (t[length - temp--] - 48);
        case 5:        result += 10000 * (t[length - temp--] - 48);
        case 4:        result += 1000 * (t[length - temp--] - 48);
        case 3:        result += 100 * (t[length - temp--] - 48);
        case 2:        result += 10 * (t[length - temp--] - 48);
        case 1:        result += 1 * (t[length - temp--] - 48);
    }

    return result;
}

Автор: Lazin 18.3.2009, 15:30
Цитата(GrayCardinal @  18.3.2009,  15:18 Найти цитируемый пост)
Да вроде Си гарантирует int - 32 бита

а почему у меня на ATmega128 sizeof(int) был равен двум? smile 

Цитата(azesmcar @  18.3.2009,  15:15 Найти цитируемый пост)
например как? мне нужен int (т.е. 32 бита) для какого типа данных С++ гарантирует 32 бита?

int32_t, int16_t, int8_t etc
можно сделать отдельный заголовочный файл в котором определить подобные типы для разных платформ

Добавлено через 2 минуты и 7 секунд
Цитата(azesmcar @  18.3.2009,  15:25 Найти цитируемый пост)
но точной гарантии на размер он однозначно не дает

он дает гарантии для диапазона значений, которые могут вмещать фундаментальные типы данных

Автор: azesmcar 18.3.2009, 15:39
Цитата

int32_t, int16_t, int8_t etc
можно сделать отдельный заголовочный файл в котором определить подобные типы для разных платформ 


в принципе я сейчас не могу предугадать все варианты smile но можно сделать заголовочный файл и определить типы для 386 платформы, а там видно будет..когда придется делать build под что-то еще - просто добавлю эти типы в заголовочный файл. Идея в принципе подходит..странно что я сам не додумался smile спасибо.

Автор: GrayCardinal 18.3.2009, 15:50
Цитата

а почему у меня на ATmega128 sizeof(int) был равен двум?

Хм. Я как-то не удосуживался это проверить. Всё больше на асме... А раз sizeof(int) двум... Что ж, очень жаль :(

Добавлено @ 15:59
Цитата

int32_t, int16_t, int8_t etc

Так это ж stdint.h подключаешь и получаешь эти типы... если не ошибаюсь...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)