Russian Qt Forum
Май 18, 2012, 18:45 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

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

Страниц: 1 [2]   Вниз
  Печать  
Автор Тема: Клиент-сервер(мультитрит): передача открытого сокета из одного Thread в другой  (Прочитано 3043 раз)
maxxant
Новичок

Offline Offline

Сообщений: 34


« Ответ #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
Чайник
*
Offline Offline

Сообщений: 62


Пишу на C++ за еду :)


« Ответ #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
Новичок

Offline Offline

Сообщений: 34


« Ответ #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
Чайник
*
Offline Offline

Сообщений: 62


Пишу на C++ за еду :)


« Ответ #18 : Февраль 03, 2010, 12:48 »

спасибо большое. Попытаюсь применить Ваш рецепт.
Записан

Обличие глупца —вот мудрость мудреца
Страниц: 1 [2]   Вверх
  Печать  
 
Перейти в:  

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