Форум программистов, компьютерный форум, киберфорум
Наши страницы
C++ Qt
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.77/13: Рейтинг темы: голосов - 13, средняя оценка - 4.77
kiko335
0 / 0 / 0
Регистрация: 13.07.2015
Сообщений: 18
1

QTcpSocket Simple Example

29.07.2015, 10:42. Просмотров 2436. Ответов 6
Метки нет (Все метки)

Есть вот такой код.
mainwindow.h
Кликните здесь для просмотра всего текста
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
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
 
#include <QTcpSocket>
#include <QMainWindow>
#include <QXmlStreamReader>
#include <QDebug>
#include <QTime>
#include <QDataStream>
 
namespace Ui {
class MainWindow;
}
 
class MainWindow : public QMainWindow
{
    Q_OBJECT
 
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
 
private:
    Ui::MainWindow *ui;
    QTcpSocket *sock;
 
private slots:
    void connect_Sock();
    void disconnect_Sock();
    void send_Ping();
    void login();
 
};
 
#endif // MAINWINDOW_H

mainwindow.cpp
Кликните здесь для просмотра всего текста
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include "mainwindow.h"
#include "ui_mainwindow.h"
 
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
 
/*  Тестовое подключение
 *  sock = new QTcpSocket(this);
    sock->connectToHost("192.168.0.120",5039);
 
    if(!sock->waitForConnected(3000))
    {
        ui->textBrowser->setText(sock->errorString());
    }
    else
    {
        qDebug() << "Connected to asterisk!";
 
        sock->waitForBytesWritten(1000);
        sock->waitForReadyRead(3000);
        qDebug() << sock->readAll();
 
        sock->write("Action: Login\nUsername: abills_admin\nSecret: Password\n\n");
        sock->waitForBytesWritten(1000);
        sock->waitForReadyRead(3000);
 
        QByteArray data =  sock->readAll();
        QString strng;
        strng.append(data);
        ui->textBrowser->append("Login - ");
        ui->textBrowser->append(strng);
 
 
        sock->write("Action: Logoff\n\n");
        sock->waitForBytesWritten(3000);
        sock->waitForReadyRead(3000);
        qDebug() << sock->readAll();
    }*/
    sock = new QTcpSocket(this);
 
    connect(ui->btn_connect, SIGNAL(clicked()), this, SLOT(connect_Sock()));
    connect(ui->btn_disconnect, SIGNAL(clicked()), this, SLOT(disconnect_Sock()));
    connect(ui->btn_ping, SIGNAL(clicked()), this, SLOT(send_Ping()));
    connect(ui->btn_login, SIGNAL(clicked()), this, SLOT(login()));
 
 
 
}
 
MainWindow::~MainWindow()
{
    delete ui;
}
 
void MainWindow::connect_Sock()
{
    ui->browser_dbg->clear();
    sock->connectToHost("192.168.0.120", 5039);
    if(!sock->waitForConnected(3000))
        ui->browser_dbg->append(sock->errorString());
    QTime time;
    sock->waitForBytesWritten(3000);
    sock->waitForReadyRead(3000);
    QByteArray data;
 
    data.append(sock->readAll());
    QString strng;
    strng.append(data);
    ui->browser_dbg->append(time.currentTime().toString() + " " + strng);
 
 
}
 
void MainWindow::disconnect_Sock()
{
    ui->browser_dbg->clear();
    sock->write("Action: Logoff\n");
    sock->write("\n");
    sock->waitForBytesWritten(3000);
    sock->waitForReadyRead(3000);
    QString ok;
    QByteArray okay;
    QTime time;
    okay.append(sock->readAll());
    ok = okay;
    ui->browser_dbg->setText(time.currentTime().toString() + " " + ok);
 
    sock->close();
    ui->browser_dbg->append(time.currentTime().toString() + " " + "Socket closed!");
}
 
void MainWindow::send_Ping()
{
    ui->browser_dbg->clear();
    sock->write("Action: Ping\n");
    sock->write("\n");
    sock->waitForBytesWritten(3000);
    sock->waitForReadyRead(3000);
    QString ok;
    QByteArray okay;
    QTime time;
    okay.append(sock->readAll());
    ok.append(okay);
    ui->browser_dbg->setText(time.currentTime().toString() + " " + ok);
}
 
void MainWindow::login()
{
    ui->browser_dbg->clear();
    QByteArray data;
    QString strng;
    sock->write("Action: Login\nUsername: abills_admin\nSecret: Password\n");
    sock->write("\n");
    sock->waitForBytesWritten(3000);
    sock->waitForReadyRead(3000);
 
    data.append(sock->readAll());
    strng.append(data);
    ui->browser_dbg->append(strng);
}


Нажимая на буттоны, мне должны приходить ответы. Но проблема в том, что ответ мне выводится иногда полностью, а иногда только его часть.
Например, я нажимаю Connect. Подконектилось, пришел ответ.
Далее нажимаю Login, и тут как повезет. Может прийти весь ответ, а может только часть.
Нажимаю Ping, если после Loginа пришло не всё, то оно выводится сейчас и показывает, возможно, часть ответа для Pingа, а если повезет, то весь.
Не могу придумать, как сделать так, чтоб оно дожидалось полного ответа и выводило его. Увеличивал время для waitForBytesWritten и waitForReadyRead - думаю это была глупость.
А ещё, можно ли сделать так, чтоб, если есть новый ответ от сервера - оно автоматически вывело мне в browser_dbg?
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
29.07.2015, 10:42
Ответы с готовыми решениями:

QTcpSocket!
Необходимо, что бы клиент отсылал данные серверу (все вроде достаточно банально, не так ли?)...

QTcpSocket Qt 5
Здравствуйте. Столкнулся со странной проблемой в QTcpSocket. Для начала пролог: С год назад я...

QTcpSocket
Нужно написать сервер, который будет общаться с браузером и telnet. Сервер должен обрабатывать...

QTcpSocket
Здраствуйте. Мне нужно установить соединение с pop3 сервером. Я на эту тему погуглил и написал...

QTcpSocket
Всем привет. Ребят, мучаюсь уже очень долго, подскажите в чем проблема. Есть класс наследованый от...

6
Kurles
159 / 124 / 30
Регистрация: 30.05.2015
Сообщений: 379
29.07.2015, 10:59 2
Не используйте блокирующие функции в слотах. Исключение вызов модальных диалогов.
Почитайте документацию на QTcpSocket, убедитесь, что он является наследником от QIODevice, почитайте документацию на QIODevice, в частности про сигнал readyRead(), и перепишите программу в асинхронной манере.
1
kiko335
0 / 0 / 0
Регистрация: 13.07.2015
Сообщений: 18
29.07.2015, 11:24  [ТС] 3
Если Вам не сложно, не могли бы Вы ещё раз посмотреть на мой код?
Я переписал немного mainwindow.сpp. Ну и добавил один слот в mainwindow.h(думаю нету смысла его добавлять).
Кликните здесь для просмотра всего текста
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include "mainwindow.h"
#include "ui_mainwindow.h"
 
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
 
/*  Тестовое подключение
 *  sock = new QTcpSocket(this);
    sock->connectToHost("192.168.0.120",5039);
 
    if(!sock->waitForConnected(3000))
    {
        ui->textBrowser->setText(sock->errorString());
    }
    else
    {
        qDebug() << "Connected to asterisk!";
 
        sock->waitForBytesWritten(1000);
        sock->waitForReadyRead(3000);
        qDebug() << sock->readAll();
 
        sock->write("Action: Login\nUsername: abills_admin\nSecret: Password\n\n");
        sock->waitForBytesWritten(1000);
        sock->waitForReadyRead(3000);
 
        QByteArray data =  sock->readAll();
        QString strng;
        strng.append(data);
        ui->textBrowser->append("Login - ");
        ui->textBrowser->append(strng);
 
 
        sock->write("Action: Logoff\n\n");
        sock->waitForBytesWritten(3000);
        sock->waitForReadyRead(3000);
        qDebug() << sock->readAll();
    }*/
    sock = new QTcpSocket(this);
 
    connect(ui->btn_connect, SIGNAL(clicked()), this, SLOT(connect_Sock()));
    connect(ui->btn_disconnect, SIGNAL(clicked()), this, SLOT(disconnect_Sock()));
    connect(ui->btn_ping, SIGNAL(clicked()), this, SLOT(send_Ping()));
    connect(ui->btn_login, SIGNAL(clicked()), this, SLOT(login()));
    connect(sock, SIGNAL(readyRead()), this, SLOT(read_Data()));
 
 
}
 
MainWindow::~MainWindow()
{
    delete ui;
}
 
void MainWindow::connect_Sock()
{
    ui->browser_dbg->clear();
    sock->connectToHost("192.168.0.120", 5039);
    if(!sock->waitForConnected(3000))
        ui->browser_dbg->append(sock->errorString());
 
 
 
 
}
 
void MainWindow::disconnect_Sock()
{
    ui->browser_dbg->clear();
    sock->write("Action: Logoff\n");
    sock->write("\n");
 
    sock->close();
    ui->browser_dbg->append("Socket closed!");
}
 
void MainWindow::send_Ping()
{
    ui->browser_dbg->clear();
    sock->write("Action: Ping\n");
    sock->write("\n");
 
}
 
void MainWindow::login()
{
    ui->browser_dbg->clear();
 
    sock->write("Action: Login\nUsername: abills_admin\nSecret: Password\n");
    sock->write("\n");
 
}
 
void MainWindow::read_Data()
{
    ui->browser_dbg->clear();
    ui->browser_dbg->append("NEW DATA");
    sock->waitForBytesWritten(3000);
    sock->waitForReadyRead(3000);
    QByteArray data;
    QString data_str;
    data.append(sock->readAll());
    data_str.append(data);
 
    ui->browser_dbg->append(data_str);
 
 
}

Сейчас работает как я хочу. Но, теперь приложение подвисает при каждом выводе информации. Можете тут что то посоветовать?
0
GRomR1
0 / 0 / 0
Регистрация: 18.05.2015
Сообщений: 5
29.07.2015, 11:32 4
kiko335, вам же написали, что если не хотите чтобы ваше приложение подвисало использовать асинхронные сигналы-слоты вместо waitForBytesWritten и waitForReadyRead.
А данные от QTcpSocket так и будут идти частями (может 1 байт придти, а могут и все 10).
Здесь можно использовать буфер, или всю работу с портом осуществлять в отдельном потоке.
Хотя здесь я вам не подскажу, сам повис на этой теме.
0
kiko335
0 / 0 / 0
Регистрация: 13.07.2015
Сообщений: 18
29.07.2015, 11:35  [ТС] 5
Дело в том, что в первом варианте моей программы, всё работало без подвисаний.
И только добавив ReadyRead, она начала подвисать.
Ладно, пойду дальше читать. Спасибо за ответы.
0
Kurles
159 / 124 / 30
Регистрация: 30.05.2015
Сообщений: 379
29.07.2015, 11:36 6
в слоте read_Data вызов блокирующих методов убери, лишние они
C++ (Qt)
1
2
sock->waitForBytesWritten(3000);
sock->waitForReadyRead(3000);
вот эти.
1
kiko335
0 / 0 / 0
Регистрация: 13.07.2015
Сообщений: 18
29.07.2015, 17:12  [ТС] 7
Не знаю как отвечать по нику, но, Kurles, большое спасибо тебе. Помогло и работает как надо.

Добавлено через 5 часов 22 минуты
Появился ещё один вопрос. Я ответы от сервера записываю append-ом в qtextbrowser. Делая qtextbrowers->find() - оно ничего не находит. Ни через регулярки, ни через обычный поиск строки. Кто то может подсказать как это лучше сделать?
0
29.07.2015, 17:12
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.07.2015, 17:12

Qt и QTcpSocket
Доброе время суток ув. Коллеги! суть вопроса следующая: разрабатываю клиент-серверное приложение,...

QTcpSocket клиент
Пишу приложение для отправки запросов серверу и считывание их. Отправка происходит, но нет сигнала...

Наследник QTcpSocket
У меня есть наследник сокетов class Client : public QTcpSocket он добавляет пару методов и...


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

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.