crossplatform.ru

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

> "Склеивание" сообщений ТСР
pwp2008
  опции профиля:
сообщение 19.10.2015, 19:31
Сообщение #1


Студент
*

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

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




Репутация:   0  


Подскажите пож-та, встречалось ли Вам отправленные друг за другом сообщения (клиентом) получать в сервере "склееном" виде, как если бы это было одно сообщение. В чем причина такой работы по протоколу TCP\IP ? Разрулить эту проблему удалось несколько искусственным способом, хотя здесь может подойти и передача длины сообщения и/или контрольный суммы. Видимо так склеены могут быть не 2, а даже больше последовательных сообщений.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
 
Начать новую тему
Ответов
ViGOur
  опции профиля:
сообщение 27.10.2015, 10:30
Сообщение #2


Мастер
******

Группа: Модератор
Сообщений: 3296
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 4

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




Репутация:   40  


4 байта было сказано для примера, ты сам решай, какой длины будет у тебя поле длина пакета. К тому же жестко указывать размер нельзя, а только sizeof(int), так как под разными системами int разного размера.
4 байта могут так же прийти по частям, это маловероятно, но может быть, например при медленном соединении или при крайней загруженности системы или сети.
Блоки не переставляются и контрольные суммы по идее не нужны, так как TCP протокол гарантирует доставку пакета
Набросал на коленке пример реализации:
struct sDataPacket
{
    int nLen;
    char *pData;
};

sDataPacket *getPacket( int socket )
{
    sDataPacket *pPacket = new sDataPacket;
    // Читаем первые 4 байта
    int nLen = sizeof(pPacket->nLen);
    char *pBuff = new char[nLen];
    do
    {
        int nRet = recv( socket, pBuff, nLen, 0 );
        if( nRet == sizeof(pPacket->nLen) )
        {
            // Переводим прочитанные 4 байта в длину
            memcpy((void*)&pPacket->nLen, (void*)pBuff, nLen);
            // Читаем указанное количество байт данных
            if( pPacket->nLen > 0 )
            {
                pPacket->pData = new char[pPacket->nLen];
                nRet = recv( socket, pPacket->pData, pPacket->nLen, 0 );
                if( nRet < pPacket->nLen )
                {
                    // Дочитываем
                }
            }
            break;
        }
        else
        {
            // Дочитываем
        }
    }while(true);
    delete []pBuff;

    return pPacket;
}
Тебе только осталось дописать докачку...

Как вариант, во избежании склеивания, можно сделать клиент серверный диалог с подтверждением, например:
1. Клиент отправляет пакет
2. Сервер получает пакет
3. Сервер отправляет подтверждение о получении пакета
4. Клиент получает подтверждени и идет к 1 пункту
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
pwp2008
  опции профиля:
сообщение 27.10.2015, 19:49
Сообщение #3


Студент
*

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

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




Репутация:   0  


Цитата(ViGOur @ 27.10.2015, 10:30) *
4 байта было сказано для примера, ты сам решай, какой длины будет у тебя поле длина пакета. К тому же жестко указывать размер нельзя, а только sizeof(int), так как под разными системами int разного размера.
............................

Большое спасибо за пример. Еще, если можно, ряд уточнений.
1. Для моей задачи длина сообщений от 14 до 130 байт, поэтому вполне для длины хватит и 1-го байта.
Прилично ли считывать 1 байт? Хотя, судя по тому, что и 4 байта могут идти частями, думаю, что вполне
прилично.
2. Посоветуйте, какая технология может быть, чтобы не было 2-го входа в слот по сигналу ReadyRead ?
Ведь вполне возможно, что пока я буду выделять и возможно обрабатывать "склееные" сообщения и\или
ждать пока соберется все "разрезанное" сообщение, система может мне устроить второй вход в незаконченный
слот. Реентерабельность тут как то не просматривается.
Не снимать же connect по входу в слот обработки и назначать его потом снова перед выходом?
signal(readyRead)\slot -> обработка сообщений ТСР по идеологии Qt.
Я конечно попробую разобраться с вышеприведенным примером, т.к. в QT для сокета нет метода recv.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Сообщений в этой теме


Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


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




RSS Текстовая версия Сейчас: 22.11.2024, 16:05