赞
踩
TCP通信协议是面向对象,可靠的连接服务,正因为这是它最大的特点,因此在诸多领域应用广泛,在使用Qt进行面向对象的设计的时候,也常常用到TCP通信,而在Qt中,TCP协议被封装成了一个更易调用的类。此篇博文将使用Qt中的TCP通信来实现客户端和服务端的连接交互通信,以此作为延伸。
在之前的一篇博文中 ,Linux中C语言构建TCP通信,使用了C语言对TCP协议进行调用,来实现客户端和服务端的通信连接。而Qt中的TCP通信连接步骤和C语言中原生tcp连接的步骤一样,大体都是分为以下大类
区别在于,Qt中调用TCP的方式简单,可以实现如下的效果
以下是详细的实际实现
TCP协议通信逻辑图有下图,根据此逻辑图,可以更好的理解Qt中的TCP协议的调用
创建widget项目,除自有界面外,再添加一个新的界面,构建如下图所示的项目文件树
客户端界面构建
服务端界面构建
两个界面大体是构建上面是显示消息栏。下面是输入消息发送栏。
第一步需要在项目的pro文件中添加网络通信模块
QT += network
首先需要添加所需头文件,用于tcp通信
#include <QTcpSocket>
之后是tcp通信的类的声明以及一个相应键盘事件的事件过滤器
private:
QTcpSocket *tcpSocket;
protected:
bool eventFilter(QObject *target, QEvent *event);//事件过滤器
};
同样是添加所需工具头文件
#include <QHostAddress>
#include <QDebug>
#include <QTime>
#include <QKeyEvent>
之后是构造函数和部分相关函数的设计
ClientWidget::ClientWidget(QWidget *parent) : QWidget(parent), ui(new Ui::ClientWidget) { ui->setupUi(this); this->setWindowTitle("客户端"); this->resize(500,300); this->setMinimumSize(500,300); tcpSocket = new QTcpSocket(this); connect(tcpSocket,&QTcpSocket::connected, [=]() { ui->textEditRead->setText("与服务器成功连接"); qDebug() << "连接成功"; } ); connect(tcpSocket,&QTcpSocket::readyRead, [=]() { QByteArray array = tcpSocket->readAll(); ui->textEditRead->append(array); } ); ui->ButtonSend->setFocus(); ui->ButtonSend->setDefault(true); //ui->ButtonSend->setShortcut(Qt::Key_Enter|Qt::Key_Return); ui->textEditWrite->installEventFilter(this);//设置完后自动调用其eventFilter函数 } ClientWidget::~ClientWidget() { delete ui; } void ClientWidget::on_ButtonConnect_clicked() { //获取服务器端口和ip QString ip = ui->lineEditIp->text(); qint16 port = ui->lineEditPort->text().toInt(); //与服务器进行连接 tcpSocket->connectToHost(QHostAddress(ip),port); } void ClientWidget::on_ButtonSend_clicked() { //获取编辑框内容 QTime cur_time = QTime::currentTime(); QString str = ui->textEditWrite->toPlainText(); QString time_info = cur_time.toString("hh:mm:ss"); QString str_info = QString("客户端: %1 [%2]").arg(str).arg(time_info); //发送数据 tcpSocket->write(str_info.toUtf8().data()); ui->textEditWrite->clear(); //ui->textEditWrite->setFocus(); } void ClientWidget::on_ButtonClose_clicked() { //主动断开连接 tcpSocket->disconnectFromHost(); ui->textEditRead->setText("与服务器断开连接!"); tcpSocket->close(); }
添加头文件
#include <QTcpServer> //监听套接字
#include <QTcpSocket> //通信套接字
通信套接字声明实现和事件过滤器
private:
QTcpServer *tcpServer;
QTcpSocket *tcpSocket;
protected:
bool eventFilter(QObject *target, QEvent *event);//事件过滤器
添加工具头文件
#include <QTime>
#include <QKeyEvent>
构造函数设计
ServerWidget::ServerWidget(QWidget *parent) : QWidget(parent), ui(new Ui::ServerWidget) { ui->setupUi(this); tcpServer = NULL; tcpSocket = NULL; // tcpServer = new QTcpServer(this); tcpSocket = new QTcpSocket(this); tcpServer->listen(QHostAddress::Any,8888); this->setWindowTitle("服务器(端口:8888)"); this->resize(500,300); this->setMinimumSize(500,300); connect(tcpServer,&QTcpServer::newConnection, [=]() { //取出建立好连接的套接字 tcpSocket = tcpServer->nextPendingConnection(); //获取对方的ip和端口s static QString ip = tcpSocket->peerAddress().toString(); static qint16 port = tcpSocket->peerPort(); QString temp = QString("[%1:%2] : 成功连接").arg(ip).arg(port); ui->textEditRead->setText(temp); connect(tcpSocket,&QTcpSocket::readyRead, [=]() { //从通信套接字中取出内容 QByteArray array = tcpSocket->readAll(); ui->textEditRead->append(array); //追加添加内容 } ); } ); // connect(tcpSocket,&QTcpSocket::readyRead, // [=]() // { // //从通信套接字中取出内容 // QByteArray array = tcpSocket->readAll(); // ui->textEditRead->append(array); //追加添加内容 // } // ); ui->ButtonSend->setFocus(); ui->ButtonSend->setDefault(true); //ui->ButtonSend->setShortcut(Qt::Key_Enter|Qt::Key_Return); ui->textEditWrite->installEventFilter(this);//设置完后自动调用其eventFilter函数 }
经此设计构建之后可以实现如上的功能操作,有此基础之后可以自定定义自己的服务器,如智能小车的控制,摄像头图像的传递识别等等
#ifndef CLIENTWIDGET_H #define CLIENTWIDGET_H #include <QWidget> #include <QTcpSocket> namespace Ui { class ClientWidget; } class ClientWidget : public QWidget { Q_OBJECT public: explicit ClientWidget(QWidget *parent = nullptr); ~ClientWidget(); private slots: void on_ButtonSend_clicked(); void on_ButtonConnect_clicked(); void on_ButtonClose_clicked(); private: Ui::ClientWidget *ui; private: QTcpSocket *tcpSocket; protected: bool eventFilter(QObject *target, QEvent *event);//事件过滤器 }; #endif // CLIENTWIDGET_H
#include "clientwidget.h" #include "ui_clientwidget.h" #include <QHostAddress> #include <QDebug> #include <QTime> #include <QKeyEvent> ClientWidget::ClientWidget(QWidget *parent) : QWidget(parent), ui(new Ui::ClientWidget) { ui->setupUi(this); this->setWindowTitle("客户端"); this->resize(500,300); this->setMinimumSize(500,300); tcpSocket = new QTcpSocket(this); connect(tcpSocket,&QTcpSocket::connected, [=]() { ui->textEditRead->setText("与服务器成功连接"); qDebug() << "连接成功"; } ); connect(tcpSocket,&QTcpSocket::readyRead, [=]() { QByteArray array = tcpSocket->readAll(); ui->textEditRead->append(array); } ); ui->ButtonSend->setFocus(); ui->ButtonSend->setDefault(true); //ui->ButtonSend->setShortcut(Qt::Key_Enter|Qt::Key_Return); ui->textEditWrite->installEventFilter(this);//设置完后自动调用其eventFilter函数 } ClientWidget::~ClientWidget() { delete ui; } void ClientWidget::on_ButtonConnect_clicked() { //获取服务器端口和ip QString ip = ui->lineEditIp->text(); qint16 port = ui->lineEditPort->text().toInt(); //与服务器进行连接 tcpSocket->connectToHost(QHostAddress(ip),port); } void ClientWidget::on_ButtonSend_clicked() { //获取编辑框内容 QTime cur_time = QTime::currentTime(); QString str = ui->textEditWrite->toPlainText(); QString time_info = cur_time.toString("hh:mm:ss"); QString str_info = QString("客户端: %1 [%2]").arg(str).arg(time_info); //发送数据 tcpSocket->write(str_info.toUtf8().data()); ui->textEditWrite->clear(); //ui->textEditWrite->setFocus(); } void ClientWidget::on_ButtonClose_clicked() { //主动断开连接 tcpSocket->disconnectFromHost(); ui->textEditRead->setText("与服务器断开连接!"); tcpSocket->close(); } bool ClientWidget::eventFilter(QObject *target, QEvent *event) { if(target == ui->textEditWrite) { if(event->type() == QEvent::KeyPress)//回车键 { QKeyEvent *k = static_cast<QKeyEvent *>(event); if(k->key() == Qt::Key_Return) { on_ButtonSend_clicked(); return true; } } } return QWidget::eventFilter(target,event); }
#ifndef SERVERWIDGET_H #define SERVERWIDGET_H #include <QWidget> #include <QTcpServer> //监听套接字 #include <QTcpSocket> //通信套接字 namespace Ui { class ServerWidget; } class ServerWidget : public QWidget { Q_OBJECT public: explicit ServerWidget(QWidget *parent = nullptr); ~ServerWidget(); protected: bool eventFilter(QObject *target, QEvent *event);//事件过滤器 private slots: void on_ButtonClose_clicked(); void on_ButtonSend_clicked(); private: Ui::ServerWidget *ui; private: QTcpServer *tcpServer; QTcpSocket *tcpSocket; // QString ip; // qint16 port; }; #endif // SERVERWIDGET_H
#include "serverwidget.h" #include "ui_serverwidget.h" #include <QTime> #include <QKeyEvent> ServerWidget::ServerWidget(QWidget *parent) : QWidget(parent), ui(new Ui::ServerWidget) { ui->setupUi(this); tcpServer = NULL; tcpSocket = NULL; // tcpServer = new QTcpServer(this); tcpSocket = new QTcpSocket(this); tcpServer->listen(QHostAddress::Any,8888); this->setWindowTitle("服务器(端口:8888)"); this->resize(500,300); this->setMinimumSize(500,300); connect(tcpServer,&QTcpServer::newConnection, [=]() { //取出建立好连接的套接字 tcpSocket = tcpServer->nextPendingConnection(); //获取对方的ip和端口s static QString ip = tcpSocket->peerAddress().toString(); static qint16 port = tcpSocket->peerPort(); QString temp = QString("[%1:%2] : 成功连接").arg(ip).arg(port); ui->textEditRead->setText(temp); connect(tcpSocket,&QTcpSocket::readyRead, [=]() { //从通信套接字中取出内容 QByteArray array = tcpSocket->readAll(); ui->textEditRead->append(array); //追加添加内容 } ); } ); // connect(tcpSocket,&QTcpSocket::readyRead, // [=]() // { // //从通信套接字中取出内容 // QByteArray array = tcpSocket->readAll(); // ui->textEditRead->append(array); //追加添加内容 // } // ); ui->ButtonSend->setFocus(); ui->ButtonSend->setDefault(true); //ui->ButtonSend->setShortcut(Qt::Key_Enter|Qt::Key_Return); ui->textEditWrite->installEventFilter(this);//设置完后自动调用其eventFilter函数 } ServerWidget::~ServerWidget() { delete ui; } bool ServerWidget::eventFilter(QObject *target, QEvent *event) { if(target == ui->textEditWrite) { if(event->type() == QEvent::KeyPress)//回车键 { QKeyEvent *k = static_cast<QKeyEvent *>(event); if(k->key() == Qt::Key_Return) { on_ButtonSend_clicked(); return true; } } } return QWidget::eventFilter(target,event); } void ServerWidget::on_ButtonSend_clicked() { if(tcpSocket == NULL) { return ; } //获取编辑区内容 QTime cur_time = QTime::currentTime(); QString str = ui->textEditWrite->toPlainText(); QString time_info = cur_time.toString("hh:mm:ss"); QString str_info = QString("服务器: %1 [%2]").arg(str).arg(time_info); tcpSocket->write(str_info.toUtf8().data()); ui->textEditWrite->clear(); } void ServerWidget::on_ButtonClose_clicked() { if(tcpSocket == NULL) //主动与客户端断开连接 tcpSocket->disconnectFromHost(); static QString ip = tcpSocket->peerAddress().toString(); static qint16 port = tcpSocket->peerPort(); QString showtemp = QString("[%1:%2] : 断开连接").arg(ip).arg(port); ui->textEditRead->setText(showtemp); tcpSocket->close(); //this->close(); tcpSocket = NULL; }
详细效果,可戳传送门下载体验传送门
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。