Russian Qt Forum
Ноябрь 23, 2024, 22:28 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Как отсылать клиенту пакеты строго 64 к ?  (Прочитано 6085 раз)
AntonUfo
Гость
« : Октябрь 24, 2011, 16:21 »

Столкнулся с тем что при отсылке сервером клиенту сообщения больше 64к, сообщения не приходят, подскажите плз, как переделать данный кусок кода что бы клиенту высылались данные пакетами 64К ?

Код:
void EchoThread::recievmessages( const QString &strmessage, const QString &arg ){
    QByteArray block2;
    QDataStream out(&block2, QIODevice::WriteOnly);
  
    out.setVersion(QDataStream::Qt_4_4);
    out << (quint16)0; // конец блока

    out << arg;            //куда отправляем сообщение
    out << strmessage; //строка сообщения

    out.device()->seek(0); //подсчет колличества байтов в сформированном пакете и отсылка информации
    quint16 byte = (block2.size() - sizeof(quint16));
    out << byte; //подсчитаем реальный размер блока в байтах

    emit writeToSocket(block2);
}

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


UPD: В сокет пишу так:

//для отправки данных сокетом клиенту
connect(this, SIGNAL(writeToSocket(QByteArray)), m_client, SLOT(onWrite(QByteArray)) );


//непосредственно отправляем данные сокетом
void TcpSocket::onWrite(QByteArray block2){
   this->write(block2);
}


Проблема в том что к примеру строка "Тестовая строка" передается нормально, а  строка из 1000 символов нет !
« Последнее редактирование: Октябрь 24, 2011, 16:51 от AntonUfo » Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #1 : Октябрь 24, 2011, 16:30 »

Покажи как в сокет пишешь.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #2 : Октябрь 24, 2011, 21:14 »

Столкнулся с тем что при отсылке сервером клиенту сообщения больше 64к
...
а строка из 1000 символов нет!
1000 символов - это (в зависмости от кодировки) 1000~4000 байт, что явно меньше 64к.
А так можете попробовать после write вызывать waitForBytesWritten( -1 ).
Записан
AntonUfo
Гость
« Ответ #3 : Октябрь 25, 2011, 08:12 »

Столкнулся с тем что при отсылке сервером клиенту сообщения больше 64к
...
а строка из 1000 символов нет!
1000 символов - это (в зависмости от кодировки) 1000~4000 байт, что явно меньше 64к.
А так можете попробовать после write вызывать waitForBytesWritten( -1 ).

все равно ничего не получается ! я уже просто не знаю куда копать....
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #4 : Октябрь 25, 2011, 08:33 »

Стоп:
Код:
quint16 byte = (block2.size() - sizeof(quint16));
quint16 какой диапазон имеет? 0~65535
То есть при длине сообщения более 64к вы заполняете поле длины неверными данными.

Если сервер ваш, то покажите и код чтения. Может и там косяки есть.
Записан
AntonUfo
Гость
« Ответ #5 : Октябрь 25, 2011, 08:44 »

Стоп:
Код:
quint16 byte = (block2.size() - sizeof(quint16));
quint16 какой диапазон имеет? 0~65535
То есть при длине сообщения более 64к вы заполняете поле длины неверными данными.

Если сервер ваш, то покажите и код чтения. Может и там косяки есть.



Вот код код клиента который получает сообщения:

Код:
//Получаем данные от сервера, и вывожу полученную информацию в нужные места в клиенте
void ClientRam::updateTcpWidget()
{
QString arg;
QString strmessage;

    QDataStream in(&tcpSocket);
    in.setVersion(QDataStream::Qt_4_4);

viewResultAction->setEnabled(true);
forever {

        if (nextBlockSize == 0) {
            if (tcpSocket.bytesAvailable() < sizeof(quint16))
                break;
            in >> nextBlockSize;
        }

        if (nextBlockSize == 0xFFFF) {
connectUp = false;
            closeConnection();
            break;
        }

        if (tcpSocket.bytesAvailable() < nextBlockSize)
            break;

in >> arg;
in >> strmessage;

//вывод информации в поле вывода
if (arg == tr( "вывод" )){
emit recievmessages(strmessage); //вывожу информацию в поле вывода....
}
//вывод информации в статусбар
if (arg == tr( "статус" )){
statusBar()->showMessage(strmessage );//вывожу информацию в статус бар....
}

nextBlockSize = 0; //готовы получить новую порцию данных
}//конец forever
}
« Последнее редактирование: Октябрь 25, 2011, 08:53 от AntonUfo » Записан
Янковский Александр
Гость
« Ответ #6 : Октябрь 25, 2011, 10:54 »

По UDP более 64 кБ не отправишь за один раз.
Каждая датаграмма (если не ошибаюсь 512 байт) клеится операционной системой как раз до размера 64 кБ.

Выход конечно же есть. Но нужно уже строить что-то более высокое, чем просто запихнуть данные в сокет.
А именно завести 2 счетчика:
  1) номер массива (сквозной);
  2) номер блока данных внутри массива (от 0 до N)

Ну и соответственно паковать данные. В начале идет структура с указанными выше значениями счетчиков + фактический размер данных, запиханных в эту пачку (64 кБ максимум).

Ну и потом естественно сами данные, но не более чем весь возможный массив.

Удачи!
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #7 : Октябрь 25, 2011, 11:53 »

По UDP более 64 кБ не отправишь за один раз.
tcpSocket. При чём тут UDP?

Код:
if (nextBlockSize == 0xFFFF)
Что за «магическая константа», если вы предполагаете, что у вас длина блока может быть более 64к (а значит и ровно 0xFFFF)?

Код:
if (tcpSocket.bytesAvailable() < nextBlockSize)
            break;
С чего вы решили, что тут надо выходить? Ну недошли ещё все данные, надо ж подождать (continue) а не выходить (break).

Про идентификацию пакетов русскими словами я вообще промолчу.

Код
C++ (Qt)
void ClientRam::updateTcpWidget()
{
QString arg;
QString strmessage;
 
   QDataStream in(&tcpSocket);
   in.setVersion(QDataStream::Qt_4_4);
 
viewResultAction->setEnabled(true);
while ( tcpSocket.state() == QAbstractSocket::ConnectedState ) {
 
       if (nextBlockSize == 0) {
           if (tcpSocket.bytesAvailable() < sizeof(quint16))
               continue;
           in >> nextBlockSize;
       }
 
       if (tcpSocket.bytesAvailable() < nextBlockSize)
           continue;
 
in >> arg;
in >> strmessage;
 
//вывод информации в поле вывода
if (arg == tr( "вывод" )){
emit recievmessages(strmessage); //вывожу информацию в поле вывода....
}
                      else
//вывод информации в статусбар
if (arg == tr( "статус" )){
statusBar()->showMessage(strmessage );//вывожу информацию в статус бар....
}
else
                     {
statusBar()->showMessage( "НЁХ: " + arg + ": "+ strmessage );//вывожу информацию в статус бар....
                     }
nextBlockSize = 0; //готовы получить новую порцию данных
 
}//конец forever
}

Если нужны пакеты длиннее 65535 байт менятьтип поля размера в заголовке с quint16 на quint32 или quint64.
Записан
RedDog
Гость
« Ответ #8 : Октябрь 25, 2011, 12:52 »

К стати, по поводу QDataStream через сокеты. Как то пытался отправлять файлы пакетами по 64к через него, и почему то к каждому пакету примешивалось 4 байта хз откуда.
Через write(...) все прекрано работает.
Записан
ddrtn
Гость
« Ответ #9 : Октябрь 25, 2011, 13:21 »

К стати, по поводу QDataStream через сокеты. Как то пытался отправлять файлы пакетами по 64к через него, и почему то к каждому пакету примешивалось 4 байта хз откуда.
Через write(...) все прекрано работает.

В начале посылки добавлялся ее размер. Смотри про правила сериализации через QDataStream
Записан
AntonUfo
Гость
« Ответ #10 : Октябрь 26, 2011, 08:48 »

Про идентификацию пакетов русскими словами я вообще промолчу.
Если нужны пакеты длиннее 65535 байт менять тип поля размера в заголовке с quint16 на quint32 или quint64.

1. спасибо за разъяснения, поменял тип поля размера и все заработало
2. По поводу идентификации пакетов русскими словами, может быть подскажете как правильно ?
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #11 : Октябрь 26, 2011, 09:58 »

По поводу идентификации пакетов русскими словами, может быть подскажете как правильно?
Ну классический вариант - числовыми константами.
Ну или хотя бы английскими словами - не будет проблем с кодировками.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.124 секунд. Запросов: 23.