Russian Qt Forum

Qt => Вопросы новичков => Тема начата: sektor от Ноябрь 29, 2015, 15:43



Название: tcp_client
Отправлено: sektor от Ноябрь 29, 2015, 15:43
добрый день! Возникла необходимость разработать программное обеспечение, которое будет собирать значения по ЛВС с arduin. Я залил готовый скетч  echo tcp servera из библиотеки UIPEthernet.   И составил программу на в Qt, которая показана ниже.

tcp_client.h
Код:
#ifndef TCP_client_H
#define TCP_client_H

#include <QDialog>
#include <QWidget>
#include <QVBoxLayout>
#include <QTcpSocket>
#include <QTime>
#include <QDataStream>
#include <QTextEdit>
#include <QLineEdit>
#include <QLabel>
#include <QPushButton>

class TCP_client : public QDialog
{
    Q_OBJECT
private:
    QTcpSocket* m_pTcpSocket;
    quint16      m_nNextBlockSize;
    QTextEdit*     m_ptxtInfo;
    QLineEdit*      m_ptxtInput;

public:
    TCP_client (QWidget* pobj = 0);

private slots:
    void slotReadyRead();
    void slotError(QAbstractSocket::SocketError);
    void slotConnnected();
    void slotSendToServer();
};



#endif // TCP_H

tcp_client.cpp
Код:
#include "tcp_client.h"

TCP_client::TCP_client(QWidget *pwgt) :
                       QDialog(pwgt), m_nNextBlockSize(0)
{
    m_pTcpSocket = new QTcpSocket(this);

    m_pTcpSocket ->connectToHost("10.28.17.164", 1000);

    connect(m_pTcpSocket, SIGNAL(connected()), SLOT(slotConnnected()));
    connect(m_pTcpSocket, SIGNAL(readyRead()), SLOT(slotReadyRead()));
    connect(m_pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)),
            this, SLOT(slotError(QAbstractSocket::SocketError))
            );
    m_ptxtInfo =new QTextEdit;
    m_ptxtInput = new QLineEdit;

    m_ptxtInfo->setReadOnly(true);

    QPushButton* pcmd = new QPushButton("&send");
    connect(pcmd, SIGNAL(clicked()), SLOT(slotSendToServer()));
    connect(m_ptxtInput, SIGNAL(returnPressed()), this, SLOT(slotSendToServer()));

    //-------------отоброжение---------------..//

    QVBoxLayout* pvbxLayout = new QVBoxLayout;
    pvbxLayout->addWidget(new QLabel ("<H1>Client</H1>"));
    pvbxLayout->addWidget(m_ptxtInfo);
    pvbxLayout->addWidget(m_ptxtInput);
    pvbxLayout->addWidget(pcmd);
    setLayout(pvbxLayout);
}

//-----------------------передача сообщения ---------------------------------
void TCP_client::slotSendToServer()
{
    QByteArray arrBlock;
    QDataStream out(&arrBlock, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_5_5);
    out<<qint16(0) << m_ptxtInput->text();

    out.device()->seek(0);
    out<<qint16(arrBlock.size() - sizeof(qint16));

    m_pTcpSocket->write(arrBlock);
    m_ptxtInput ->setText("");


}

//--------------------считывание собщения-------------------------//
void TCP_client::slotReadyRead()
{
    QDataStream in(m_pTcpSocket);
    in.setVersion(QDataStream::Qt_5_5);
    for(;;){
        if(!m_nNextBlockSize){
            if(m_pTcpSocket->bytesAvailable()<sizeof(qint16)){
                break;
            }
            in>>m_nNextBlockSize;
        }

        if(m_pTcpSocket->bytesAvailable()<m_nNextBlockSize){
            break;
        }

        QTime time;
        QString str;
        in>>str;

        m_ptxtInfo ->append(str);
        m_nNextBlockSize = 0;
    }
}

//-----------------------------ошибки-----------------------------//
void TCP_client::slotError(QAbstractSocket::SocketError err)
{
    QString strError =
            "Error: " +(err == QAbstractSocket::HostNotFoundError ?
                            "The host is not font." :
                        err == QAbstractSocket::RemoteHostClosedError ?
                        "The remote host is closed" :
                        err == QAbstractSocket::ConnectionRefusedError ?
                        "The conection was refused" :
                        QString (m_pTcpSocket->errorString())
                        );
    m_ptxtInfo ->append( strError);

}

void TCP_client::slotConnnected()
{
    m_ptxtInfo ->append("Соеденение устанволенно!");
}

Все работает отлично, то что я отправляю получаю обратно, но в терминале arduino получаю значение с пробелами.
(http://)
 Читал вот это http://meshin1.tumblr.com/post/254097090/%D1%80%D0%B0%D0%B7%D0%B1%D0%B8%D1%80%D0%B0%D0%B5%D0%BC%D1%81%D1%8F-%D1%81-%D1%81%D0%B5%D1%80%D0%B8%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B5%D0%B9-%D0%B2-qiodevice (http://meshin1.tumblr.com/post/254097090/%D1%80%D0%B0%D0%B7%D0%B1%D0%B8%D1%80%D0%B0%D0%B5%D0%BC%D1%81%D1%8F-%D1%81-%D1%81%D0%B5%D1%80%D0%B8%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B5%D0%B9-%D0%B2-qiodevice). Как можно по другому реализовать код? Или как можно от дополнительный передающих байтов избавиться?
С perl скриптом все работает нормально
Код:
#!/usr/bin/perl
#tcpclient.pl

use IO::Socket::INET;

# flush after every write
$| = 1;

my ($socket,$client_socket);

# creating object interface of IO::Socket::INET modules which internally creates
# socket, binds and connects to the TCP server running on the specific port.
$socket = new IO::Socket::INET (
PeerHost => '192.168.0.6',
PeerPort => '1000',
Proto => 'tcp',
) or die "ERROR in Socket Creation : $!\n";

print "TCP Connection Success.\n";

# write on the socket to server.
$data = "DATA from Client";
print $socket "$data\n";
# we can also send the data through IO::Socket::INET module,
# $socket->send($data);

# read the socket data sent by server.
$data = <$socket>;
# we can also read from socket through recv()  in IO::Socket::INET
# $socket->recv($data,1024);
print "Received from Server : $data\n";

sleep (10);
$socket->close();


Название: Re: tcp_client
Отправлено: Old от Ноябрь 29, 2015, 19:09
Вы отправляете UNICODE строку, которая храниться в QString. Конвертируйте ее в однобайтные кодировки перед отправкой, с помощью QTextCodec.


Название: Re: tcp_client
Отправлено: sektor от Ноябрь 29, 2015, 21:08
Я извиняюсь я начинающий программист. Прошу помощи  :). 
Цитировать
Вы отправляете UNICODE строку, которая храниться в QString. Конвертируйте ее в однобайтные кодировки перед отправкой, с помощью QTextCodec.

Так чтоли ?
Код:
void TCP_client::slotSendToServer()
{
    QByteArray arrBlock;
    QDataStream out(&arrBlock, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_5_5);
    out<<qint16(0) << m_ptxtInput->text();

    out.device()->seek(0);
    out<<qint16(arrBlock.size() - sizeof(qint16));
    QTextCodec* data;
    m_pTcpSocket->write(data->toUnicode(arrBlock));
    m_ptxtInput ->setText("");


}


Название: Re: tcp_client
Отправлено: Old от Ноябрь 29, 2015, 21:27
Код
C++ (Qt)
QTextCodec *codec = QTextCodec::codecForName( "UTF-8" );
out<<qint16(0) << codec->fromUnicode( m_ptxtInput->text() );
 
Так мы пишем в поток QByteArray, т.е. вначале идет длина массива (quint32), а потом данные.
Если длину сохранять не надо, то придется использовать writeBytes.


Название: Re: tcp_client
Отправлено: sektor от Ноябрь 29, 2015, 21:56
Сделал как вы сказали.  Да, действительно пробелы между символами пропали, но, что то передается до нужный символов пробелы (см. рис). Ну естественно так как я поменял функцию передачи, моя функция приема не правильно обрабатывает и ничего не принимает обратно  :(

Код:
void TCP_client::slotSendToServer()
{
    QByteArray arrBlock;
    QDataStream out(&arrBlock, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_5_5);
    QTextCodec *codec = QTextCodec::codecForName( "UTF-8" );
    out<<qint16(0) << codec->fromUnicode( m_ptxtInput->text() );

    out.device()->seek(0);
    
    out<<qint16(arrBlock.size() - sizeof(qint16));

    m_pTcpSocket->write(arrBlock);
    m_ptxtInput ->setText("");


}
Код:
 out<<qint16(arrBlock.size() - sizeof(qint16));
что это выражение значит ?


Название: Re: tcp_client
Отправлено: Old от Ноябрь 29, 2015, 23:18
В тех пробельных символах и передается размер QByteArray.
Вам не нужно использовать QDataStream, он пишет кроме самой строки еще и служебную информацию - размер массива.
Пишите только строку:
Код
C++ (Qt)
void TCP_client::slotSendToServer()
{
   QTextCodec *codec = QTextCodec::codecForName( "UTF-8" );
   m_pTcpSocket->write( codec->fromUnicode( m_ptxtInput->text() ) );
   m_ptxtInput ->setText("");
}
 


Название: Re: tcp_client
Отправлено: sektor от Ноябрь 30, 2015, 00:14
Спасибо большое Вы мне очень помогли. Не сможете помочь с функцией приема ?


Название: Re: tcp_client
Отправлено: Old от Ноябрь 30, 2015, 07:50
Спасибо большое Вы мне очень помогли. Не сможете помочь с функцией приема ?
Да все наоборот:
read
toUnicode


Название: Re: tcp_client
Отправлено: sektor от Ноябрь 30, 2015, 14:39
Что то не получается у меня  >:(
Код:
QByteArrey data;
QTextCodec* codec = QTextCodec::codecForName("UTF-8");
m_pTcpSocket->read(data);
m_ptxtInfo->append(codec->fromUnicode(data.toStdString());


Название: Re: tcp_client
Отправлено: Old от Ноябрь 30, 2015, 14:58
Что то не получается у меня  >:(
Пока вы не начнете читать документацию и не начнет получаться. ;)

Код
C++ (Qt)
QTextCodec* codec = QTextCodec::codecForName("UTF-8");
QByteArrey data = m_pTcpSocket->readAll();
m_ptxtInfo->append(codec->fromUnicode(data.toStdString());
 


Название: Re: tcp_client
Отправлено: sektor от Ноябрь 30, 2015, 16:40
Спасибо, с английским чуть проблемы  :)


Название: Re: tcp_client
Отправлено: sektor от Ноябрь 30, 2015, 17:27
выдает ошибку
Код:
conversion from 'std::string(aka std::basic_string<char>) to non scalar type QString reguested


Название: Re: tcp_client
Отправлено: Old от Ноябрь 30, 2015, 17:45
выдает ошибку
Код:
conversion from 'std::string(aka std::basic_string<char>) to non scalar type QString reguested
Это я у вас копипастнул и не посмотрел. Не нужно data делать никаких toStdString. Просто передайте data.