crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

2 страниц V   1 2 >  
Ответить в данную темуНачать новую тему
> Прием данных по сокету. Какие конвенции лучше?
Andrewshkovskii
  опции профиля:
сообщение 8.12.2011, 11:03
Сообщение #1


Активный участник
***

Группа: Участник
Сообщений: 351
Регистрация: 27.12.2008
Пользователь №: 467

Спасибо сказали: 18 раз(а)




Репутация:   1  


Есть клиент и сервер. Постоянно обмениваются сообщениями разной длинны.
Сейчас, что бы понять, где кончается одно сообщение и начинается другое, используется конвенция сообщений такая :
Цитата
%длина_всего_соообщения%|%тело сообщения%


Но с этим иногда бывают косяки. Есть ли какие-то ещё конвенции или парадигмы, как лучше общаться сокетам большими сообщениями?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
sidsukana
  опции профиля:
сообщение 8.12.2011, 11:21
Сообщение #2


Участник
**

Группа: Участник
Сообщений: 158
Регистрация: 23.12.2010
Из: Челябинск
Пользователь №: 2296

Спасибо сказали: 10 раз(а)




Репутация:   2  


А чем тебя не устраивает обмениваться структурами?
Если у тебя клиент и сервер знают

struct Message
{
    quint32 size;
    QString msg;
};

void read()
{
    QByteArray buffer;
    // читаем первые 4 байта размер блока текста
    buffer = read(4);
    quint32 size = buffer.toUInt();

    buffer = read(size);
    QString str = buffer.data();
}


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

Сообщение отредактировал sidsukana - 8.12.2011, 11:21
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
kuzulis
  опции профиля:
сообщение 8.12.2011, 12:17
Сообщение #3


Активный участник
***

Группа: Участник
Сообщений: 393
Регистрация: 29.6.2009
Пользователь №: 862

Спасибо сказали: 36 раз(а)




Репутация:   7  


Цитата
Есть ли какие-то ещё конвенции или парадигмы, как лучше общаться сокетам большими сообщениями?


man это и это

Обычно "парадигмы" это запрос/ответ или посылка/подтверждение.

Структуры кадров в общем случае выглядят: <header><body><trailer>

Где header, body, trailer - это поля кадра.

в header, например, могут указываться маркёры + биты направлений + биты типа пакета (первый/не первый/последний) + номер пакета + длина последующих данных body
в body собственно, данные.
в trailer, например, могут указываться маркёры + CRC

Если сообщение уж оч длинное, то можешь разбить свою "подпрограмму" обработки сообщений на два ISO/ISI уровня: грубо канальный + приложения.

Твое приложение будет принимать готовое здоровенное сообщение из уровня приложения и писать в уровень приложения.
Уровень приложения принимает от здоровенное сообщение от программы, дробит его на части, и отсылает канальному(или физическому - пофик как назовешь), который оборачивает в <header><body><trailer>
и шлет в сокет с обязательным ожиданием ACK от удаленной стороны.
И так до конца, пока Уровень приложения не передаст все части этого сообщения.

В обратку - канальный уровень из сокета принимает кусок данных как <header><body><trailer>, проверяет header, trailer . Если все ОК,
то он обрезает header, trailer, вынимает кусок body и передает его наверх в Уровень приложения. Если какая-то хрень с header, trailer,
то канальный уровень перезапрашивает этот кусок.
Уровень приложения принимает body от канального, и для уровня приложения этот же body будет выглядеть как <header2><body2><trailer2>
оно это проверяет, извлекает body2 и накапливает эти куски в своем буфере (добавляет каждый следующий кусок). И когда Уровень приложения
примет от канального <header2><body2><trailer2> с указанным в header2 флагом о том, что это последний кусок - то
Уровень приложения добавляет этот кусок в свой буфер и возвращает этот буфер приложению. Этот буфер и будет сообщением.

Ведь нисколечки не сложно? Правда ведь? :rolleyes:

Можешь посмотреть тут , оч познавательная статья.
Можешь адаптировать для себя например протокол X-Modem или еще что нить.

Это если тебе нужна надежность!!!

Сообщение отредактировал kuzulis - 8.12.2011, 12:21
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ssoft
  опции профиля:
сообщение 8.12.2011, 13:34
Сообщение #4


Участник
**

Группа: Участник
Сообщений: 130
Регистрация: 17.2.2010
Из: Москва
Пользователь №: 1470

Спасибо сказали: 30 раз(а)




Репутация:   3  


Цитата(Andrewshkovskii @ 8.12.2011, 12:03) *
Но с этим иногда бывают косяки.


Что за косяки?
Пока не сталкивался. Очень хотелось бы узнать.

Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Andrewshkovskii
  опции профиля:
сообщение 8.12.2011, 14:05
Сообщение #5


Активный участник
***

Группа: Участник
Сообщений: 351
Регистрация: 27.12.2008
Пользователь №: 467

Спасибо сказали: 18 раз(а)




Репутация:   1  


Цитата(kuzulis @ 8.12.2011, 12:17) *
Цитата
Есть ли какие-то ещё конвенции или парадигмы, как лучше общаться сокетам большими сообщениями?


man это и это

Обычно "парадигмы" это запрос/ответ или посылка/подтверждение.

Структуры кадров в общем случае выглядят: <header><body><trailer>

Где header, body, trailer - это поля кадра.

в header, например, могут указываться маркёры + биты направлений + биты типа пакета (первый/не первый/последний) + номер пакета + длина последующих данных body
в body собственно, данные.
в trailer, например, могут указываться маркёры + CRC

Если сообщение уж оч длинное, то можешь разбить свою "подпрограмму" обработки сообщений на два ISO/ISI уровня: грубо канальный + приложения.

Твое приложение будет принимать готовое здоровенное сообщение из уровня приложения и писать в уровень приложения.
Уровень приложения принимает от здоровенное сообщение от программы, дробит его на части, и отсылает канальному(или физическому - пофик как назовешь), который оборачивает в <header><body><trailer>
и шлет в сокет с обязательным ожиданием ACK от удаленной стороны.
И так до конца, пока Уровень приложения не передаст все части этого сообщения.

В обратку - канальный уровень из сокета принимает кусок данных как <header><body><trailer>, проверяет header, trailer . Если все ОК,
то он обрезает header, trailer, вынимает кусок body и передает его наверх в Уровень приложения. Если какая-то хрень с header, trailer,
то канальный уровень перезапрашивает этот кусок.
Уровень приложения принимает body от канального, и для уровня приложения этот же body будет выглядеть как <header2><body2><trailer2>
оно это проверяет, извлекает body2 и накапливает эти куски в своем буфере (добавляет каждый следующий кусок). И когда Уровень приложения
примет от канального <header2><body2><trailer2> с указанным в header2 флагом о том, что это последний кусок - то
Уровень приложения добавляет этот кусок в свой буфер и возвращает этот буфер приложению. Этот буфер и будет сообщением.

Ведь нисколечки не сложно? Правда ведь? :rolleyes:

Можешь посмотреть тут , оч познавательная статья.
Можешь адаптировать для себя например протокол X-Modem или еще что нить.

Это если тебе нужна надежность!!!

Я вроде говорил о том, что над протоколом, а не внутри. Зачем Вы мне все это написали? Я не протокол пишу, а пытаюсь понять - как лучше передавать сообщения между сокетами, что бы соблюдалась целостность при передаче данных кусками (именно так оно работает в реальности).

Косяки в производителельности таких алгоритмов разбора сообщения - операции со строками в основном.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
kuzulis
  опции профиля:
сообщение 8.12.2011, 14:43
Сообщение #6


Активный участник
***

Группа: Участник
Сообщений: 393
Регистрация: 29.6.2009
Пользователь №: 862

Спасибо сказали: 36 раз(а)




Репутация:   7  


Цитата
Я вроде говорил о том, что над протоколом, а не внутри. Зачем Вы мне все это написали?

Я тебе и написал про "НАД".

Цитата
Я не протокол пишу, а пытаюсь понять - как лучше передавать сообщения между сокетами, что бы соблюдалась целостность при передаче данных кусками (именно так оно работает в реальности).

Я тебе написал как. Если не понимаешь - то брось это дело.
Без некоего протокола передачи - у тебя ничего не получится. Бросай в общем..
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ssoft
  опции профиля:
сообщение 8.12.2011, 15:43
Сообщение #7


Участник
**

Группа: Участник
Сообщений: 130
Регистрация: 17.2.2010
Из: Москва
Пользователь №: 1470

Спасибо сказали: 30 раз(а)




Репутация:   3  


Цитата(Andrewshkovskii @ 8.12.2011, 15:05) *
Косяки в производителельности таких алгоритмов разбора сообщения - операции со строками в основном.


Здесь есть пример сборки сообщения из сокета.
сборка сообщения
Никаких операций со строками производить не нужно.
С одной стороны отправил QByteArray, с другой получил.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Andrewshkovskii
  опции профиля:
сообщение 8.12.2011, 16:09
Сообщение #8


Активный участник
***

Группа: Участник
Сообщений: 351
Регистрация: 27.12.2008
Пользователь №: 467

Спасибо сказали: 18 раз(а)




Репутация:   1  


Цитата(kuzulis @ 8.12.2011, 14:43) *
Цитата
Я вроде говорил о том, что над протоколом, а не внутри. Зачем Вы мне все это написали?

Я тебе и написал про "НАД".

Цитата
Я не протокол пишу, а пытаюсь понять - как лучше передавать сообщения между сокетами, что бы соблюдалась целостность при передаче данных кусками (именно так оно работает в реальности).

Я тебе написал как. Если не понимаешь - то брось это дело.
Без некоего протокола передачи - у тебя ничего не получится. Бросай в общем..

Не брошу.

Цитата(ssoft @ 8.12.2011, 15:43) *
Цитата(Andrewshkovskii @ 8.12.2011, 15:05) *
Косяки в производителельности таких алгоритмов разбора сообщения - операции со строками в основном.


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

Дело в том, что я все это для питона собираю - там я использую строки и сериализованный json, а не bytearray.
Кстати, вот код, если кому интересно :
def on_ready_read(self):
        data = str(self.readAll())
        while data:
            if not self.wait_len and '|' in data:#new data and new message
                    self.wait_len , data = data.split('|',1)
                    if match('[0-9]+', self.wait_len) and (len(self.wait_len) <= MAX_WAIT_LEN) and data[0]=='{':#okay, this is normal length
                        self.wait_len = int(self.wait_len)
                        self.temp = data[:self.wait_len]
                        data = data[self.wait_len:]
                    else:#oh, it was crap
                        self.wait_len , self.temp = '',''
                        return
            elif self.wait_len:#okay, not new message, appending
                self.temp+=data[:(self.wait_len-len(self.temp))]
                data=data[len(self.temp):]
            elif not self.wait_len and not '|' in data:#crap
                return
            if self.wait_len and self.wait_len == len(self.temp):#okay, full message
                    self.data_ready.emit(self.temp)
                    self.wait_len ,self.temp = '',''
                    if not data:
                        return


Сообщение отредактировал Andrewshkovskii - 8.12.2011, 19:08
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Влад
  опции профиля:
сообщение 9.12.2011, 15:45
Сообщение #9


Участник
**

Группа: Участник
Сообщений: 146
Регистрация: 20.3.2009
Из: Санкт-Петербург
Пользователь №: 627

Спасибо сказали: 46 раз(а)




Репутация:   8  


Цитата(Andrewshkovskii @ 8.12.2011, 12:03) *
Но с этим иногда бывают косяки. Есть ли какие-то ещё конвенции или парадигмы, как лучше общаться сокетам большими сообщениями?

А какой протокол используется у тебя на транспортном уровне?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Andrewshkovskii
  опции профиля:
сообщение 9.12.2011, 16:26
Сообщение #10


Активный участник
***

Группа: Участник
Сообщений: 351
Регистрация: 27.12.2008
Пользователь №: 467

Спасибо сказали: 18 раз(а)




Репутация:   1  


Цитата(Влад @ 9.12.2011, 15:45) *
Цитата(Andrewshkovskii @ 8.12.2011, 12:03) *
Но с этим иногда бывают косяки. Есть ли какие-то ещё конвенции или парадигмы, как лучше общаться сокетам большими сообщениями?

А какой протокол используется у тебя на транспортном уровне?

TCP. В общем, косяк был в алгоритме , я его переписал. Пока всё ок , но есть проблемы, когда пакеты теряются. Тогда, конечно, алгоритму беда.

Сообщение отредактировал Andrewshkovskii - 14.12.2011, 23:01
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

2 страниц V   1 2 >
Ответить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 28.3.2024, 15:38