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

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

Страниц: 1 [2]   Вниз
  Печать  
Автор Тема: Клиент-сервер(мультитрит): передача открытого сокета из одного Thread в другой  (Прочитано 12131 раз)
maxxant
Гость
« Ответ #15 : Февраль 03, 2010, 10:58 »

Почему byteArray не копируется в QString, а при этом вот такая конструкция for (int k=0;k<8;k++) send.append((char)byteArray[k]); прекрасно собирает слово. Миллион и один способ пробовал, ничего не получается Грустный.

лучше миллион и один раз посмотреть доки с примерами. Вы сериализуете один тип, а десериализуется другой. Десериализация должна быть строго симметричной. Иначе результат не предсказуем. Можете для примера сравнить разницу операторов сериализации для QByteArray и QString:

Код
C++ (Qt)
QDataStream &operator<<(QDataStream &out, const QByteArray &ba)
{
   if (ba.isNull() && out.version() >= 6) {
       out << (quint32)0xffffffff;
       return out;
   }
   return out.writeBytes(ba, ba.size());
}
 
QDataStream &operator<<(QDataStream &out, const QString &str)
{
   if (out.version() == 1) {
       out << str.toLatin1();
   } else {
       if (!str.isNull() || out.version() < 3) {
           int byteOrder = out.byteOrder();
           const QChar* ub = str.unicode();
           static const uint auto_size = 1024;
           char t[auto_size];
           char *b;
           if (str.length()*sizeof(QChar) > auto_size) {
               b = new char[str.length()*sizeof(QChar)];
           } else {
               b = t;
           }
           int l = str.length();
           char *c=b;
           while (l--) {
               if (byteOrder == QDataStream::BigEndian) {
                   *c++ = (char)ub->row();
                   *c++ = (char)ub->cell();
               } else {
                   *c++ = (char)ub->cell();
                   *c++ = (char)ub->row();
               }
               ub++;
           }
           out.writeBytes(b, sizeof(QChar)*str.length());
           if (str.length()*sizeof(QChar) > auto_size)
               delete [] b;
       } else {
           // write null marker
           out << (quint32)0xffffffff;
       }
   }
   return out;
}
Записан
hackoff
Гость
« Ответ #16 : Февраль 03, 2010, 11:34 »

Идею понял! Спасибо!
Но появилась другая проблема.
В клиенте пишу
Код:
    QPixmap pix=screenShot();
    QIODevice * socket = (QIODevice*)this;
    QDataStream data(socket);
    data.setVersion(QDataStream::Qt_4_6);
    QString send("send-screen");
    data<<send<<pix<<QString("end");

На сервере читаю
Код:
void connectionTCP::ready_read(){
    QIODevice * socket = (QIODevice*)this;
    QDataStream data(socket);
    data.setVersion(QDataStream::Qt_4_6);
    QByteArray byteArray;
    QString str, str2;
    QPixmap pix;
    data>>str;
    data>>pix;
    data>>str2;
    qDebug()<<str<<pix.size()<<str2;
}

Дебаг выводит
Цитировать

"send-screen" QSize(-1, -1) ""
"" QSize(-1, -1) ""
"" QSize(-1, -1) ""
..................................
"" QSize(-1, -1) ""
"" QSize(-1, -1) ""

Почему изображение и последняя строка не читаются?
Записан
maxxant
Гость
« Ответ #17 : Февраль 03, 2010, 12:44 »

Дебаг выводит
Цитировать

"send-screen" QSize(-1, -1) ""
"" QSize(-1, -1) ""
"" QSize(-1, -1) ""
..................................
"" QSize(-1, -1) ""
"" QSize(-1, -1) ""

Почему изображение и последняя строка не читаются?

Сигнал readyRead() присылается при получении пакета данных. Вероятно, когда вы его получаете, данные пришли ещё не все, сокет просто не может логически разделить пакеты так как вам необходимо . Возможно проблема сейчас и не в этом, но столкнуться с этим придётся, поэтому сразу реализуйте проверку на кол-во данных. Здесь на форуме уже писали (вроде и я писал) как поступить в этом случае. Есть метод bytesAvailable() у QIODevice и есть ваш пакет данных, размер которого необходимо знать до отправки, соответственно при приёме можно вычислить все ли необходимые данные уже находиться в буфере сокета, после чего считывать.
Если на вскидку, то всё просто, писать сначала в QByteArray а потом его и отправлять:

отправка:
Код
C++ (Qt)
   ...
   QByteArray msg;
   QDataStream stream(&msg, QIODevice::WriteOnly);
   stream.setVersion(QDataStream::Qt_4_6);
   stream << some_data;
   stream << some_data;
   stream << some_data;
 
   sendPacket(msg);
}
 
void sendPacket(QByteArray data)
{
   qint32 _size = data.size();
   if(data.size())
   {
       p_ioDevice->write((char*)&_size, sizeof(_size));
       p_ioDevice->write(data);
       qDebug() << "[net] send packet with size:" << data.size();
   }
}
 
quint32 чтобы работало везде на 32-х и на 64-х битах одинаково
p_ioDevice - это сокет.

получение:
Код
C++ (Qt)
 
void net::ready_read() // from signal readyRead()
{
   while(checkMessage())
   {
       qint32 _size=0;
       QByteArray data;
       // read packet size
       qint64 _readed = p_ioDevice->read((char*) &_size, sizeof(_size));
       if((sizeof(_size)==_readed) && (_size>0))
       {
          // read data
          data = p_ioDevice->read(_size);
          if(data.size() != _size)
          {
              // error!!!
              // disconnect,  ...
              return;
          }
 
          packet_ready(data);
       }
   }
}
 
bool net::checkMessage()
{
   // check packet size
   qint32 _size=0;
   qint64 _bytes_available = p_ioDevice->bytesAvailable();
   if(_bytes_available < sizeof(_size)) return false;
 
   qint64 _peek_size = p_ioDevice->peek((char*)&_size, sizeof(_size));
   if(_peek_size != sizeof(_size)) return false;
   if(0 == _size)
   {
       p_ioDevice->read(4); // empty packet
       return false;
   }
   _bytes_available = p_ioDevice->bytesAvailable();
   if(_bytes_available < sizeof(_size) + _size) return false;
   return true;
}
 
void net::packet_ready(QByteArray msg)
{
   QDataStream stream(&msg, QIODevice::ReadOnly);
   stream.setVersion(QDataStream::Qt_4_6);
   stream >> some_data
   stream >> some_data
   ...
}
 
Записан
hackoff
Гость
« Ответ #18 : Февраль 03, 2010, 12:48 »

спасибо большое. Попытаюсь применить Ваш рецепт.
Записан
Страниц: 1 [2]   Вверх
  Печать  
 
Перейти в:  


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