我正在为放置在循环中的客户端创建服务器-客户端系统,以不断地从服务器查询预定的信息集。根据我对Qt框架的TCP实现如何工作的了解,我已经编写了一些代码,但是我不确定我编写的内容是否是正确的方法。
首先,我在客户端QTcp类中创建了带有一堆QByteArray
变量的枚举,作为查询从客户端传递到服务器,如下所示
enum datamap
{
QByteArray data1 = 1;
QByteArray data2 = 2;
QByteArray data3 = 3;
// and so on...
};
然后我制作一个函数,该函数需要一个枚举datamap
变量来传递给服务器,并使用一个变量来容纳当前请求(以避免为错误的请求接收到的数据之间的混淆),如下所示
datamap current_request = 0;
int client::setDataToGet(datamap& data)
{
if(socket->state() == QAbstractSocket::ConnectedState)
{
current_request = data;
socket->write(data);
return socket->waitForBytesWritten();
}
else
return -1;
}
此后,我创建一个readyRead()
插槽,该插槽连接到readyread
信号以处理来自服务器的响应,并发送到函数,这些函数将根据{在相应的文本框中显示接收到的数据。 {1}}变量,如下所示
current_request
现在,对于服务器端,我创建了一个void client::readyRead()
{
QTcpSocket *m_socket = static_cast<QTcpSocket*>(sender());
while(m_socket->bytesAvailable() > 0)
{
QByteArray buf = socket->readAll();
}
switch(current_request):
case 1:
dispToTextBox1(buf);
case 2:
dispToTextBox2(buf);
case 3:
dispToTextBox3(buf);
// and so on....
}
插槽,该插槽从readyRead()
函数中调用的套接字侦听器连接到readyread()
信号。
这从客户端获取了句柄,因此应该返回与该句柄关联的数据。该插槽的代码如下
newConnection()
有人可以验证这是否是正确的方法,或者是否有更好的替代方法来处理任务。
答案 0 :(得分:0)
使概念模型可以进行一些更改。使用this问题中“ sashoalm”给出的响应来使用QdataStream传递数据,并使用信号和插槽来循环遍历每种请求类型的读写序列。
我的服务器类如下
tcpserver.h
#ifndef TCPSERVER_H
#define TCPSERVER_H
#include<qt5/QtNetwork/QTcpServer>
#include<qt5/QtNetwork/QTcpSocket>
#include<qt5/QtCore/QObject>
class TCPServer : public QObject
{
Q_OBJECT
public:
explicit TCPServer(QObject *parent = nullptr);
signals:
void dataReceived(QByteArray);
private slots:
void newConnection();
void disconnected();
void readyRead();
private:
QTcpServer *server;
QTcpSocket *socket;
QHash<QString, int> reverse_hash;
};
#endif // TCPSERVER_H
tcpserver.cpp
#include <iostream>
#include "tcpserver.h"
#include <qt5/QtCore/QDataStream>
#include <qt5/QtCore/QBuffer>
#include <qt5/QtCore/QString>
class BlockWriter
{
public:
BlockWriter(QIODevice *io)
{
buffer.open(QIODevice::WriteOnly);
this->io = io;
_stream.setVersion(QDataStream::Qt_4_8);
_stream.setDevice(&buffer);
_stream << quint64(0);
}
~BlockWriter()
{
_stream.device()->seek(0);
_stream << static_cast<quint64>(buffer.size());
io->write(buffer.buffer());
}
QDataStream &stream()
{
return _stream;
}
private:
QBuffer buffer;
QDataStream _stream;
QIODevice *io;
};
class BlockReader
{
public:
BlockReader(QIODevice *io)
{
buffer.open(QIODevice::ReadWrite);
_stream.setVersion(QDataStream::Qt_4_8);
_stream.setDevice(&buffer);
qint64 blockSize;
readMax(io, sizeof(blockSize));
buffer.seek(0);
_stream >> blockSize;
readMax(io, blockSize);
buffer.seek(sizeof(blockSize));
}
QDataStream& stream()
{
return _stream;
}
private:
void readMax(QIODevice *io, qint64 n)
{
while (buffer.size() < n) {
buffer.write(io->read(n - buffer.size()));
}
}
QBuffer buffer;
QDataStream _stream;
};
TCPServer::TCPServer(QObject *parent) : QObject(parent)
{
server = new QTcpServer(this);
connect(server, SIGNAL(newConnection()), SLOT(newConnection()));
qDebug() << "Listening:" << server->listen(QHostAddress::Any, 5404);
reverse_hash.insert("data1", 1);
reverse_hash.insert("data2", 2);
}
void TCPServer::newConnection()
{
while (server->hasPendingConnections())
{
qDebug()<<"incoming connection!";
socket = server->nextPendingConnection();
connect(socket, SIGNAL(readyRead()), SLOT(readyRead()));
connect(socket, SIGNAL(disconnected()), SLOT(disconnected()));
}
}
void TCPServer::disconnected()
{
qDebug() << "disconnected!";
disconnect(socket, SIGNAL(readyRead()));
disconnect(socket, SIGNAL(disconnected()));
socket->deleteLater();
}
void TCPServer::readyRead()
{
qDebug() << "Read!";
QString data;
BlockReader(socket).stream() >> data;
qDebug() <<"received data request: " << data;
switch(reverse_hash.value(data))
{
case 1: //call sequence to respond to request.(write to data)
qDebug() << "responding go data1 request!";
break;
case 2://call sequence to respond to request.(write to data)
qDebug() << "responding go data2 request!";
break;
}
BlockWriter(socket).stream()<<data;
socket->flush();
}
我的客户端GUI类如下
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtNetwork>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
QTcpSocket *socket;
QHash<int, QString> hash;
int current_slot, starting_slot, ending_slot;
signals:
void dataSet();
public slots:
void connectToHost();
void connected();
void disconnected();
void setDatatoGet();
void getData();
//bool writeData(QByteArray data);
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <iostream>
class BlockWriter
{
public:
BlockWriter(QIODevice *io)
{
buffer.open(QIODevice::WriteOnly);
this->io = io;
_stream.setVersion(QDataStream::Qt_4_8);
_stream.setDevice(&buffer);
_stream << quint64(0);
}
~BlockWriter()
{
_stream.device()->seek(0);
_stream << static_cast<quint64>(buffer.size());
io->write(buffer.buffer());
}
QDataStream &stream()
{
return _stream;
}
private:
QBuffer buffer;
QDataStream _stream;
QIODevice *io;
};
class BlockReader
{
public:
BlockReader(QIODevice *io)
{
buffer.open(QIODevice::ReadWrite);
_stream.setVersion(QDataStream::Qt_4_8);
_stream.setDevice(&buffer);
qint64 blockSize;
readMax(io, sizeof(blockSize));
buffer.seek(0);
_stream >> blockSize;
readMax(io, blockSize);
buffer.seek(sizeof(blockSize));
}
QDataStream& stream()
{
return _stream;
}
private:
void readMax(QIODevice *io, qint64 n)
{
while (buffer.size() < n) {
buffer.write(io->read(n - buffer.size()));
}
}
QBuffer buffer;
QDataStream _stream;
};
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
starting_slot = 1;
current_slot = starting_slot;
ending_slot = 2;
ui->setupUi(this);
ui->status_label->setStyleSheet("background-color:red;");
ui->receive_btn->setEnabled(false);
socket = new QTcpSocket(this);
connectToHost();
connect(ui->conn_btn, SIGNAL(clicked()), this, SLOT(connectToHost()));
connect(ui->receive_btn, SIGNAL(clicked()), this, SLOT(setDatatoGet()));
connect(this, SIGNAL(dataSet()), this , SLOT(setDatatoGet()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::connectToHost()
{
socket->deleteLater();
socket = new QTcpSocket(this);
socket->connectToHost(QHostAddress("192.168.0.127"), 5404);
connect(socket, SIGNAL(connected()), this, SLOT(connected()));
connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()));
//ADD to hash table
hash.insert(1, "data1");
hash.insert(2, "data2");
}
void MainWindow::connected()
{
ui->status_label->setStyleSheet("background-color:green;");
ui->receive_btn->setEnabled(true);
connect(socket, SIGNAL(readyRead()),this, SLOT(getData()));
}
void MainWindow::disconnected()
{
ui->status_label->setStyleSheet("background-color:red;");
ui->receive_btn->setEnabled(false);
disconnect(socket, SIGNAL(readyRead()),this, SLOT(getData()));
}
void MainWindow::setDatatoGet()
{
if(current_slot == ending_slot + 1)
{
current_slot = starting_slot;
}
qDebug() <<"calling request data slot " << current_slot;
BlockWriter(socket).stream() << hash.value(current_slot);
socket->flush();
current_slot++;
}
void MainWindow::getData()
{
QString data;
BlockReader(socket).stream() >> data;
//qDebug() <<"received response, current received data is for slot "<< data <<"and current number is" << current_slot;
switch (current_slot - 1)
{
case 1:
//display in respective label
qDebug() << "display data1 to label!";
break;
case 2:
//display in respective label
qDebug() << "display data2 to label!";
break;
}
emit dataSet();
}