Форум программистов, компьютерный форум, киберфорум
C++ Qt
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.77/13: Рейтинг темы: голосов - 13, средняя оценка - 4.77
6 / 6 / 1
Регистрация: 18.12.2013
Сообщений: 114
1

Прием числовых типов по TCP/IP

26.05.2014, 17:04. Показов 2666. Ответов 15
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем привет!!!
В общем на линукс машине есть программа сервера, на моем компе программа клиента. С клиента отправляется массив команд, а сервер на них отвечает.

код сервера
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
int tcp_server::run_community()
{
    double buf[3];
    int read_buf[3];
    int commx, commy, commz;
    int bytes_read;     
    
    double roll=0, pitch=0, yaw=0;
    roll = 213.6;
   
    
    buf[0] = 213.4;
    buf[1] = 234.7;
    buf[2] = 324.9;
    
   
    create_server();
    
 if (bind(listener, (struct sockaddr*)&addr, sizeof(addr)) < 0)
    {
        perror("bind");
        return 2;
    }
    
    listen(listener, 1);
    
    while(1)
    {
        sock = accept(listener, NULL, NULL);
        if(sock < 0)
        {
            perror("accept");
            return 3;
        }
        
        while(1)
        {   bytes_read = recv(sock, read_buf, 12, 0);
            if (bytes_read <= 0) break;
            commx = ntohl(read_buf[0]);
            commy = ntohl(read_buf[1]);
            commz = ntohl(read_buf[2]);
            
            
            printf("we rec %i , %i , %i  \n ", commx, commy, commz);
         if(commx == 0) send(sock, buf , 3*sizeof(double) , 0);
        }
        close(sock);
    }
    return 0;
}
В общем сервер с клиента, который написаный с помошью QT, нормально принимает, но когда я пытаюсь принять ответ от сервера, то данные приходят неверные
Вот код приема:
C++ (Qt)
1
2
3
4
5
6
7
8
void IMU_Tcp_Client::slotReadyRead()
{
      QDataStream in(tcpSocket);
      double yaw, pitch, roll;
      in >> yaw >> pitch >> roll;
      qDebug() << yaw << pitch << roll;
     
}
Как правильно принять массив?
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
26.05.2014, 17:04
Ответы с готовыми решениями:

Преобразование числовых типов
Добрый день. При написании программы возникла необходимость прочитать цифры из строки. Но при...

TCP SO_KEEPALIVE и таймаут на прием
Есть клиент, должен посылать несколько запросов подряд, поставил SO_SND+RCVTIMEO, решил добавить...

Прием сообщений через TCP в 1с
добрый день. Есть программа написанная на c# которая по TCP передает определенные сообщения. нужно...

Прием данных по протоколу TCP
Делаю программу, которая принимает данные по TCP протоколу с помощью сокета. Данные представляют...

15
1443 / 1326 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
26.05.2014, 17:38 2
Поиграйся с порядком бит
C++ (Qt)
1
void QDataStream::setByteOrder ( ByteOrder bo )
0
6 / 6 / 1
Регистрация: 18.12.2013
Сообщений: 114
26.05.2014, 18:19  [ТС] 3
Попробовал, не помогло.
0
Почетный модератор
11525 / 4320 / 448
Регистрация: 12.06.2008
Сообщений: 12,412
26.05.2014, 19:28 4
А структуры не используются? Если они используются с одной стороны, то и с другой должна быть точно такая же структура. Дело в том, что переменные внутри структуры выравниваются и их расположение может быть не таким, как ожидалось. Например, при
C
1
2
3
4
struct {
  char a;
  int b;
};
Структура будет занимать 8 байт вместо ожидаемых пяти. После одного байта char будет ещё зарезервировано 3 байта, что бы выровнять до четырёх.

Добавлено через 2 минуты
Я слепой... тут же приведён код клиента. Не заметил вначале.
0
770 / 760 / 59
Регистрация: 06.07.2009
Сообщений: 3,021
27.05.2014, 08:32 5
Lex999, Поидее должно все правильно отображаться.
Простейший способ прояснить в чем косяк это посмотреть данные побайтово в шестнадцатеричном виде.
Посмотри как твои числа выглядят в памяти и сравни (например используя брейкпойт) с тем, что тебе пришло из сокета.
Кстати, а в линуксе разве не прямой порядок байт используется? я не помню уже.... Может просто твои числа имеют под виндой обратный порядок байт, вот всякую хрень и выводит.
0
136 / 140 / 7
Регистрация: 22.08.2011
Сообщений: 485
27.05.2014, 10:06 6
Лучший ответ Сообщение было отмечено Lex999 как решение

Решение

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//.h,h 
...
#pragma pack(push,1)                        // желательно на сервере и клиенте
...
#define _Size_otv sizeof(double)*3      // можно через енумы
 
int i,g;                                               // количество прихода и сдвиг на будущее
 
char C_R[_Size_otv];                         // можно и красивше, но           
char C_W[_Size_otv];                        // для наглядности пойдёт
 
double buf_read[3];                            // в теории тут будет ответ
...
 #pragma pack(pop)
...
 
 
//.cpp
...
connect (Socket_RAB, SIGNAL( readyRead()), this,SLOT(prsl_RabSocketAnswer()), Qt::DirectConnection);
...
connect (this,SIGNAL(sg_RabRecMsg(QByteArray)),SLOT(prsl_CreateOtvet(QByteArray));
...
void S_RAB::prsl_RabSocketAnswer()
{
    memset(C_R,0,sizeof(C_R));
 
    i=Socket_RAB->read(C_R,Socket_RAB->bytesAvailable());  // считываем сколько можно
 
    memcpy(&C_W[g],&C_R[0],i);      // заполняем дочитанное
 
    g=g+i;                                         // донакапливаем сдвиг
 
    if(i==0)                                       // конец порции посылки
    {
        return;
    }
 
    if(g>=_Size_otv)                         // в теории всё пришло
    {
        emit sg_RabRecMsg(QByteArray::fromRawData(C_W,_Size_otv)); // можно без сигнала
                                                                                                           // и тут разгребать
                                                    // зануляем всё
        memset(C_R,0,_Size_otv);
        memset(C_W,0,_Size_otv);
        g=0; i=0;
 }
 
void S_RAB::prsl_CreateOtvet(QByteArray B)
{
memset (&buf_read,0,sizeof(buf_read);
memcpy(&buf_read,B.data(),sizeof(buf_read);
}
}
Написано приблизительно... принимает через чары, но
можно принимать большие куски порций посылок, если
где надо переделать размеры и структуры... не уверен
заработает ли, но писали выше верно про выравнивания.
В своеё версии принимаю большие структуры с даблами
без проблем и переворачивааний... Типа всё... Удачи!!!
1
6 / 6 / 1
Регистрация: 18.12.2013
Сообщений: 114
27.05.2014, 11:01  [ТС] 7
solar_wind, Ну у меня две машини на линуксе, просто одна - это миникомпьютер на Archlinux, там CodeSourcery toolchain, а на компе у меня Ubuntu 13.10 и тут клиент на Qt/С++ , так что порядок байт по идее одинаковый должен быть. В любом случае спасибо.

_SASA_, Спасибо, попробую и отпишусь.

Добавлено через 31 минуту
_SASA_, Да и такой вопрос- я так понимаю что pragma используется только в связке с Microsoft?
0
136 / 140 / 7
Регистрация: 22.08.2011
Сообщений: 485
27.05.2014, 11:13 8
Цитата Сообщение от Lex999 Посмотреть сообщение
pragma используется только в связке с Microsoft
нет не только - это директива компилятору...
на в примере у меня это запрет на его авто-
выравнивание - я же указываю, его до байта.
Если увас выравнивание 4 байта, то оно тут
и не нужно: 3 дабла =12 - кратно 4, но если у
вас выравнивание 8 байт, то тогда будет Ж...
Для проверки попробуйте с сервера кинуть 4
дабла и принять их на клиенте, что выйдет?!
0
1443 / 1326 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
27.05.2014, 11:28 9
Цитата Сообщение от Lex999 Посмотреть сообщение
так что порядок байт по идее одинаковый должен быть.
Нет. Сервер отправляет как есть( если стоит x86, little-endian), клиент читает в сетевом порядке(big-endian).
0
6 / 6 / 1
Регистрация: 18.12.2013
Сообщений: 114
27.05.2014, 11:53  [ТС] 10
_SASA_, В общем попробовал, все работает без запрета на автовыравнивание как с 4-мя так и с 3-емя даблами, огромнейшее вам спасибо!!!!

Добавлено через 15 минут
Dmitriy_M, Ну Big-Endian стоит по умолчанию, да и пробовал я менять порядок байт, впринципи сейчас еще раз попробую чтоб уж точно убедится.
0
1443 / 1326 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
27.05.2014, 12:09 11
Lex999, врешь нету big-endian
C++
1
if(commx == 0) send(sock, buf , 3*sizeof(double) , 0);
0
6 / 6 / 1
Регистрация: 18.12.2013
Сообщений: 114
27.05.2014, 12:16  [ТС] 12
Ну я только на стороне клиента менял, как я понял на обоих сторонах должны быть одинаковыми?
А не могли бы вы сказать как это правильно на написать?
0
1443 / 1326 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
27.05.2014, 12:21 13
Lex999, а ntohl ты для красоты использовал?
На разных архитектурах процессоров будет разный порядок байт, поэтому и нужно договариваться.
0
6 / 6 / 1
Регистрация: 18.12.2013
Сообщений: 114
27.05.2014, 12:29  [ТС] 14
Ну тут это для конвертирования integer, а для double как это сделать?
0
1443 / 1326 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
27.05.2014, 12:33 15
Lex999, прошу прощения не заметил типы.
Посмотри что реально передается через wireshark
0
6 / 6 / 1
Регистрация: 18.12.2013
Сообщений: 114
28.05.2014, 11:09  [ТС] 16
В общем получилось решить свою проблему следующим образом. Как уже писалось выше, с сервера у меня передавались данные в формате порядка LittleEndian. На Ubuntu я принимаю это следующим образом:
C++ (Qt)
1
2
3
4
5
6
7
8
9
void MainForm::slotReadyRead()
{
    QDataStream in(tcpSocket);
    
        in.setByteOrder(QDataStream::LittleEndian);//установка порядка приема байт    
        double yaw, pitch, roll;
        in >> yaw >> pitch >> roll;
        qDebug() << qFromLittleEndian(yaw) << qFromLittleEndian(pitch) << qFromLittleEndian(roll);//конвертирование
       }
Этот метод прекрасно работает со всеми числовыми данными. Спасибо всем за помощь.
0
28.05.2014, 11:09
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
28.05.2014, 11:09
Помогаю со студенческими работами здесь

Отправка и прием TCP пакетов
Здравствуйте, пишу тсп клиент сервер. Все бы ничего но с толкнулся с такой проблемой при отправке...

Размеры числовых типов данных
Всем привет. Вопрос: Почему мой код отображает с ошибкой только значения длины числовых данных для...

Создать абстрактный базовый класс для числовых типов
Создать абстрактный базовый класс Число с виртуальной функцией изменения знака числа. Создать...

TCP прием от клиента: Сервер считывает 21 байт не за раз, а за 7 циклов
Превью. Лог от сервера И так. От клиента поступают запросы. в среднем от 20 до 30 байт. ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru