Russian Qt Forum

Qt => Работа с сетью => Тема начата: f21 от Февраль 03, 2011, 14:12



Название: qt клиент
Отправлено: f21 от Февраль 03, 2011, 14:12
доброго времени суток.
я начинающий Qt программист и передо мной была поставлена задача написать простой клиент для сервера, который находится на устройстве ICP CON и подключен к сети через Ethernet.
Сервер запрограммирован и отвечает на команды. Моя задача состоит в том, чтобы отправлять на сервер команду 22, и получать от сервера ответ, который должен содержать версию этого самого сервера, соответствующий команде #22. Написать примитивный клиент, который соединяется с сервером трудности не составило, а вот передача команды и получения ответа пока завело в тупик. Прочитанная литература и гугл подсказывает что делать это надо с помощью класса QNetworkAccessManager но как это осуществить пока остается загадкой. Есть пример как это сделано на Visual Basic и там все довольно понятно
Код:
'Client1: Used to test all simple Xserver demos

Option Explicit

Private Sub CmdClear_Click()
  List1.Clear
End Sub

Private Sub cmdClose_Click()
  cmdConnect.Enabled = True
  cmdClose.Enabled = False
  cmdSend.Enabled = False
   
  Winsock1.Close
  StatusBar1.Panels(1).Text = "Status: Disconnect."
End Sub

Private Sub cmdConnect_Click()
  Winsock1.RemoteHost = ServeripText.Text
  Winsock1.RemotePort = ServerPortText.Text
  Winsock1.Connect
End Sub

Private Sub CmdEXIT_Click()
  Winsock1.Close
  Unload Me
End Sub

Private Sub cmdSend_Click()
  If Winsock1.State = sckConnected Then
    Winsock1.SendData txtsend.Text
  Else
    MsgBox "Not currently connected"
  End If
End Sub

Private Sub Form_Load()
  Caption = "Client side host name: " & Winsock1.LocalHostName & ",   IP: " & Winsock1.LocalIP
  cmdConnect.Enabled = True
  cmdClose.Enabled = False
  cmdSend.Enabled = False
  StatusBar1.Panels(1).Text = "Status: Disconnect."
End Sub

Private Sub Winsock1_Close()
  MsgBox "Winsock1_Close"
End Sub

' Connect event fired when the client connects
Private Sub Winsock1_Connect()
  Dim vtdata As Variant
 
  If Winsock1.State = sckConnected Then
    StatusBar1.Panels(1).Text = "Status: Connection to " & Winsock1.RemoteHostIP & " successful."
    cmdConnect.Enabled = False
    cmdSend.Enabled = True
    cmdClose.Enabled = True
  End If
End Sub

' DataArrival event is fired when the Winsock1 receive data
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
  Dim vtdata As Variant
 
  Winsock1.GetData vtdata, vbString
  List1.AddItem vtdata
End Sub

Интересует как сделать нечто подобное на Qt.

Зарание спасибо


Название: Re: qt клиент
Отправлено: BRE от Февраль 03, 2011, 14:14
Посмотри на класс QTcpSocket.


Название: Re: qt клиент
Отправлено: Странник от Февраль 03, 2011, 15:48
если я не ошибаюсь, связь с ICP CON по двухпроводному интерфейсу осуществляется с использованием одного из RS протоколов. слышал что-то про версии с Ethernet, судя по всему об одной из них и речь, но протокол обмена какой? если девайс поддерживает HTTP и управляется через web-интерфейс, то QNetworkAccessManager - верное решение. если нет - как уже было сказано, сокеты.


Название: Re: qt клиент
Отправлено: f21 от Февраль 07, 2011, 12:51
Как пробовал делать:
MyClient.h
Код:
#ifndef _MyClient_h_
#define _MyClient_h_

#include <QWidget>
#include <QTcpSocket>

class QTextEdit;
class QLineEdit;

// ======================================================================
class MyClient : public QWidget {
Q_OBJECT
private:
    QTcpSocket* m_pTcpSocket;
    QTextEdit*  m_ptxtInfo;
    QLineEdit*  m_ptxtInput;
    quint16     m_nNextBlockSize;

public:
    MyClient(const QString& strHost, int nPort, QWidget* pwgt = 0) ;

private slots:
    void slotReadyRead   (                            );
    void slotError       (QAbstractSocket::SocketError);
    void slotSendToServer(                            );
    void slotConnected   (                            );
};
#endif
main.cpp
Код:
#include <QApplication>
#include "MyClient.h"

// ----------------------------------------------------------------------
int main(int argc, char** argv)
{
    QApplication app(argc, argv);
    MyClient     client("192.168.0.41", 10000);

    client.show();

    return app.exec();
}
MyClient.cpp
Код:
#include <QtNetwork>
#include <QtGui>
#include "MyClient.h"

// ----------------------------------------------------------------------
MyClient::MyClient(const QString& strHost,
                   int            nPort,
                   QWidget*       pwgt /*=0*/
                  ) : QWidget(pwgt)
                    , m_nNextBlockSize(0)
{
    m_pTcpSocket = new QTcpSocket(this);

    m_pTcpSocket->connectToHost(strHost, nPort);
    connect(m_pTcpSocket, SIGNAL(connected()), SLOT(slotConnected()));
    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;

    connect(m_ptxtInput, SIGNAL(returnPressed()),
            this,        SLOT(slotSendToServer())
           );
    m_ptxtInfo->setReadOnly(true);

    QPushButton* pcmd = new QPushButton("&Send");
    connect(pcmd, SIGNAL(clicked()), SLOT(slotSendToServer()));

    //Layout setup
    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 MyClient::slotReadyRead()
{
    QDataStream in(m_pTcpSocket);
    in.setVersion(QDataStream::Qt_4_2);
    for (;;) {
        if (!m_nNextBlockSize) {
            if (m_pTcpSocket->bytesAvailable() < sizeof(quint16)) {
                break;
            }
            in >> m_nNextBlockSize;
        }

        if (m_pTcpSocket->bytesAvailable() < m_nNextBlockSize) {
            break;
        }
        QTime   time;
        QString str;
        in >> time >> str;

        m_ptxtInfo->append(time.toString() + " " + str);
        m_nNextBlockSize = 0;
    }
}

// ----------------------------------------------------------------------
void MyClient::slotError(QAbstractSocket::SocketError err)
{
    QString strError =
        "Error: " + (err == QAbstractSocket::HostNotFoundError ?
                     "The host was not found." :
                     err == QAbstractSocket::RemoteHostClosedError ?
                     "The remote host is closed." :
                     err == QAbstractSocket::ConnectionRefusedError ?
                     "The connection was refused." :
                     QString(m_pTcpSocket->errorString())
                    );
    m_ptxtInfo->append(strError);
}

// ----------------------------------------------------------------------
void MyClient::slotSendToServer()
{
    QByteArray  arrBlock;
    QDataStream out(&arrBlock, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_2);
    out << quint16(0) << QTime::currentTime() << m_ptxtInput->text();

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

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

// ------------------------------------------------------------------
void MyClient::slotConnected()
{
    m_ptxtInfo->append("Received the connected() signal");
}

Если запускать на компьютере локальный демо-сервер то клиент успешно получает от него ответы через слот ReadyRead
(http://img7.imageshack.us/img7/9744/35454006.jpg)

При соединении с утройством есть сообщение об успешном соединении , а ответов на команды нету
(http://img204.imageshack.us/img204/1395/42272073.jpg)


Название: Re: qt клиент
Отправлено: Странник от Февраль 07, 2011, 13:48
документация по протоколу имеется? команда 22, к примеру - это строка "22", или байт 22, или, может быть, несколько байт?


Название: Re: qt клиент
Отправлено: f21 от Февраль 07, 2011, 14:18
строка 22


Название: Re: qt клиент
Отправлено: f21 от Февраль 08, 2011, 13:57
Вообщем, на девайсе сейчас веб сервера нету и http он соответственно не поддерживает, поэтому qnetworkaccessmanager не поможет. Но не понятно почему сервер не отвечает на сообщения через сокеты


Название: Re: qt клиент
Отправлено: kuzulis от Февраль 08, 2011, 14:22
Цитировать
Вообщем, на девайсе сейчас веб сервера нету и http он соответственно не поддерживает, поэтому qnetworkaccessmanager не поможет. Но не понятно почему сервер не отвечает на сообщения через сокеты
А если слать ему: QString s("22\r\n") ?


Название: Re: qt клиент
Отправлено: f21 от Февраль 08, 2011, 14:48
Убрал проверки в следующих слотах и сделал так:

Код:
void MyClient::slotReadyRead()
{
QByteArray qwe = m_pTcpSocket->readAll();
    m_ptxtInfo->append(QString(qwe));
}

void MyClient::slotSendToServer()
{
    m_pTcpSocket->write("22");
  }
и заработало  :)