crossplatform.ru

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

3 страниц V   1 2 3 >  
Тема закрытаНачать новую тему
> [РЕШЕНО] чтение sizeof( int ) в QTcpSocket
Гость_alexei_*
сообщение 25.3.2010, 12:38
Сообщение #1





Гости








    


Уважаемые знатоки, есть вопрос.

На стороне сервера на linux у меня запущена программа, которые принимает соединения. Цикл работы следующий:
1) Получаем запрос на соединений.
2) Отправляем sizeof( int ) данных - размер в байтах идущего сообщения.
3) Отправляем сами данные

Раньше был linux-клиент и все работало (читал sizeof( int ) данных, потом определенное число данных из сокета). Решил сделать клиента кроссплатформенным, пытаясь считать данные следующим путем:

QTcpSocket::read( (long long int) sizeof( int ) ); // long long int = qint64

Получаю в качестве числа несуразную величину(да и вообще когда приходят данные от сервера их вывод никоим образом не напоминает число в начале, текст в конце то что надо - а вот число, никак не знаю как правильно передавать или считывать). Чем воспользоваться? По другому передавать число или считывать?

С уважением,
Алексей.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ViGOur
  опции профиля:
сообщение 25.3.2010, 20:14
Сообщение #2


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

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

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




Репутация:   40  


1. sizeof(int) в 32 и 64 битных системах отличаются.
2. непонятно как ты записываешь размер данных, как текст или записываешь его в первые 4 или 8 байта?

Покажи код отправки.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Гость_alexei_*
сообщение 26.3.2010, 1:16
Сообщение #3





Гости








    


Цитата(ViGOur @ 25.3.2010, 20:14) *
1. sizeof(int) в 32 и 64 битных системах отличаются.
2. непонятно как ты записываешь размер данных, как текст или записываешь его в первые 4 или 8 байта?

Покажи код отправки.


1) Мне казалось по стандарту int - 4 байта везде.
2) Вот код для отправки (сначала отправляем размер данных потом сами данные):

    nbytes = write( fd, &n, sizeof( int ) );
    if( nbytes < 0 ) {
        fprintf( stderr, "Write: error writing to %d(fd) %d(int)\n", fd, n );
        return -1;
    }

    nbytes = write( fd, data, sizeof( char ) * n );
    if( nbytes < 0 ) {
        fprintf( stderr, "Write: error writing to %d(fd) %s(data)\n", fd, data );
        return -2;
    }
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 26.3.2010, 2:03
Сообщение #4


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9656
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

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




Репутация:   94  


Цитата(Гость_alexei_* @ 26.3.2010, 4:16) *
по стандарту int - 4 байта везде.
по стандарту int зависит от реализации. Гарантированную ширину имеют только его модификации с префиксом short и long, например: short int и long int

если тебе нужна гарантия ширины, то используй типы Qt:
qint32
qint64
и д.р.

Цитата(Гость_alexei_* @ 26.3.2010, 4:16) *
fd
что это такое у тебя в коде? какому типу данных соответсвует? И что за функция write, от какого класса?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Гость_alexei_*
сообщение 26.3.2010, 20:21
Сообщение #5





Гости








    


Цитата(Litkevich Yuriy @ 26.3.2010, 2:03) *
Цитата(Гость_alexei_* @ 26.3.2010, 4:16) *
по стандарту int - 4 байта везде.
по стандарту int зависит от реализации. Гарантированную ширину имеют только его модификации с префиксом short и long, например: short int и long int

если тебе нужна гарантия ширины, то используй типы Qt:
qint32
qint64
и д.р.

Цитата(Гость_alexei_* @ 26.3.2010, 4:16) *
fd
что это такое у тебя в коде? какому типу данных соответсвует? И что за функция write, от какого класса?


Серверная часть написана из соображений минимальности использования внешний библиотек (установки Qt например), поэтому там нет таких понятий как qint64. fd - файловый дескриптор сокета, в который пишем данные (тип int). Серверную часть трогать не хочется - потому что она рабочая и общается с другими сущностями по такому искусственному протоколу (если менять сервер, то менять и все остальное). Простой вывод в консоль qt-клиента вырисовывает стрелочку влево (что соответствует в таблице ascii - 28, число которое я передавал со стороны сервера). Можно ли на qt-клиенте правильно обработать эту информацию?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
alexei
  опции профиля:
сообщение 26.3.2010, 22:07
Сообщение #6


Студент
*

Группа: Новичок
Сообщений: 11
Регистрация: 26.3.2010
Пользователь №: 1570

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




Репутация:   0  


Проверил, на стороне сервера и qt-клиента размеры данных одинаковы:

size of int = 4
size of short int = 2
size of long int = 4

правда число которое я получаю посредством sscanf: 156274600 (в двоичной системе даже на смешение байтов от 28 не похоже)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 26.3.2010, 23:50
Сообщение #7


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9656
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

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




Репутация:   94  


alexei, я тебе предлагаю воспользоваться на стороне клиента функцией
QByteArray QIODevice::readAll ()
А затем преобразовать в HEX, например:

QTcpSocket socket;
QByteArray array;
array = socet.readAll();
qDebug() << "READ:" << array.toHex().toUpper();
Так ты увидишь, что ты принял, сразу в шестнадцатиричной форме.

П.С. не забывай, что пакет может фрагментироваться
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
alexei
  опции профиля:
сообщение 27.3.2010, 1:03
Сообщение #8


Студент
*

Группа: Новичок
Сообщений: 11
Регистрация: 26.3.2010
Пользователь №: 1570

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




Репутация:   0  


Цитата(Litkevich Yuriy @ 26.3.2010, 23:50) *
alexei, я тебе предлагаю воспользоваться на стороне клиента функцией
QByteArray QIODevice::readAll ()
А затем преобразовать в HEX, например:

QTcpSocket socket;
QByteArray array;
array = socet.readAll();
qDebug() << "READ:" << array.toHex().toUpper();
Так ты увидишь, что ты принял, сразу в шестнадцатиричной форме.

П.С. не забывай, что пакет может фрагментироваться


Привожу куски кода qt-клиента (каким образом происходит чтение, не понял зачем мне смотреть шестнадцатиричная форму, когда я смотрю текст в обычном для чтения представлении):

QByteArray responseArr; // элемент класса

void CClientGui::slotReadyRead() {
    int err;
    int size = 0;
    char *buf = NULL;
    int percent;
    int idTask;
    static bool flagFirst = true;

    QDomDocument loc_xmlDoc;
    QDomElement loc_xmlRootElement;

    int bytes = CClientGui::tcpSocket.bytesAvailable();
    fprintf( stdout, "available %d bytes\n", (int)bytes );
    /*
     * First message structure :
     * <answer>
     *        <id>#id</id>
     * </answer>
     */  
    if( flagFirst == true ) {        
        responseArr.append( CClientGui::tcpSocket.readAll() );
        err = readFromServer( responseArr, size, &buf );
        if( err != 0 ) {
            fprintf( stderr, "Error read from socket" );
            return;
        }
//....


int CClientGui::readFromServer( QByteArray &bufAll, int& _size, char **_buf ) {
    char *buf = NULL;
    int size;

    fprintf( stdout, "allBuf: %s\n", bufAll.data() );
    fprintf( stdout, "allBuf hex: %s\n", bufAll.toHex().data() ); // добавил вывод в 16-ричной форме

    buf = new char[sizeof(int)];
    buf = bufAll.left( sizeof( int ) ).data(); // здесь должно быть чтение байт (никакого преобразования к qint64 и тому подобным)
    fprintf( stdout, "input read: %s\n", buf );
    _size += sizeof( int );
    sscanf( buf, "%d", &size );
    fprintf( stdout, "to read: %d bytes\n", size );
    bufAll.remove(0,sizeof(int));
    buf = new char[size+1];
    strcpy( buf, bufAll.right( size ).data() );
    buf[size] = '\0';
    *_buf = buf;
    buf = NULL;
    bufAll.remove( 0, size );
    _size += size;

    return 0;
}

Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
alexei
  опции профиля:
сообщение 27.3.2010, 14:08
Сообщение #9


Студент
*

Группа: Новичок
Сообщений: 11
Регистрация: 26.3.2010
Пользователь №: 1570

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




Репутация:   0  


Спасибо за совет с hex. Действительно байты перемешались, надо правильно инициализировать соединение. Будем разбираться
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ViGOur
  опции профиля:
сообщение 27.3.2010, 14:19
Сообщение #10


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

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

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




Репутация:   40  


Попробуй читать с помощью qint64 QIODevice::read ( char * data, qint64 maxSize ), тоесть у тебя получится что-то вроде:
qint64 nRet=CClientGui::tcpSocket.read( &n, sizeof(int));
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

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


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




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