Qt TCP网络上位机的设计(通过网络编程与下位机结合)

简介: Qt TCP网络上位机的设计(通过网络编程与下位机结合)

TCP 协议基础

传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议


TCP 的拥塞控制算法(也称 AIMD 算法)。该算法主要包括四个主要部分:慢启动、拥塞避免、快速重传和快速恢复


TCP 通信必须建立 TCP 连接(客户端和服务器端),Qt 提供 QTcpSocket 类和 QTcpServer 类专门用于建立 TCP 通信程序。服务 器端用 QTcpServer 监听端口及建立服务器;QTcpSocket 用于建立 连接后使用套接字(socket)进行通信


QTcpServer 和 QAbstractSocket 主要接口函数

QTcpServer 是从 QOjbect 继承的类用于服务器建立网络监听, 创建网络 socket 连接。QTcpServer 主要接口函数如下:





QAbstractSocket主要接口函数如下:


1c354ab98d6ef2f506500bcf8683fc93_bf329e5e5ecd4d83bda3d9cf2732b888.png


TCP 应用程序

1.服务端

UI绘图:

5c2bfdebe0f59a4732bdc942301b1d0b_a3a8c0c7d9dd4f1d9f63cfa573a408f4.png

代码示例:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
 
#include <QMainWindow>
 
#include <QTcpServer> // 专门用于建立TCP连接并传输数据信息
#include <QtNetwork> // 此模块提供开发TCP/IP客户端和服务器的类
 
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
 
class MainWindow : public QMainWindow
{
    Q_OBJECT
 
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
 
private:
    Ui::MainWindow *ui;
 
 
    // 自定义如下
private:
    QTcpServer *tcpserver; //TCP服务器
    QTcpSocket *tcpsocket;// TCP通讯socket
    QString GetLocalIpAddress(); // 获取本机的IP地址
 
private slots:
    void clientconnect();
    void clientdisconnect();
    void socketreaddata();
    void newconnection();
 
 
    void on_pushButton_Start_clicked();
    void on_pushButton_Stop_clicked();
    void on_pushButton_Send_clicked();
 
protected:
    void closeEvent(QCloseEvent *event);
 
};
#endif // MAINWINDOW_H

main.cpp

#include "mainwindow.h"
 
#include <QApplication>
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
 
#include <QMessageBox>
 
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
 
    QString strip=GetLocalIpAddress();
    // QMessageBox::information(this,"数据",strip,QMessageBox::Yes);
 
    ui->comboBoxIp->addItem(strip);
 
 
    tcpserver=new QTcpServer(this);
 
    connect(tcpserver,SIGNAL(newConnection()),this,SLOT(newconnection()));
 
}
 
MainWindow::~MainWindow()
{
    delete ui;
}
 
 
void MainWindow::on_pushButton_Start_clicked()
{
    QString ip=ui->comboBoxIp->currentText();
    quint16 port=ui->spinBoxPort->value();
 
    QHostAddress address(ip);
    tcpserver->listen(address,port);
 
    ui->plainTextEdit_DispMsg->appendPlainText("$$$$$$$$$$开始监听$$$$$$$$$$");
    ui->plainTextEdit_DispMsg->appendPlainText("$$$$$$$$$$服务器地址$$$$$$$$$$:"+
                                               tcpserver->serverAddress().toString());
    ui->plainTextEdit_DispMsg->appendPlainText("$$$$$$$$$$服务器端口$$$$$$$$$$:"+
                                               QString::number(tcpserver->serverPort()));
    ui->pushButton_Start->setEnabled(false);
    ui->pushButton_Stop->setEnabled(true);
 
}
 
void MainWindow::on_pushButton_Stop_clicked()
{
    if(tcpserver->isListening())
    {
        tcpserver->close();
        ui->pushButton_Start->setEnabled(true);
        ui->pushButton_Stop->setEnabled(false);
    }
 
}
 
void MainWindow::on_pushButton_Send_clicked()
{
    QString strmsg=ui->lineEdit_InputMsg->text();
    ui->plainTextEdit_DispMsg->appendPlainText("[out]:"+strmsg);
 
    ui->lineEdit_InputMsg->clear();
 
    QByteArray str=strmsg.toUtf8();
    str.append("\n");
    tcpsocket->write(str);
}
 
 
QString MainWindow::GetLocalIpAddress() // 获取本机的IP地址
{
    QString hostname=QHostInfo::localHostName();
    QHostInfo hostinfo=QHostInfo::fromName(hostname);
 
    QString localip="";
 
    QList<QHostAddress> addresslist=hostinfo.addresses();
 
    if(!addresslist.isEmpty())
    {
        for (int i=0;i<addresslist.count();i++)
        {
            QHostAddress addrhost=addresslist.at(i);
            if(QAbstractSocket::IPv4Protocol==addrhost.protocol())
            {
                localip=addrhost.toString();
                break;
            }
 
        }
    }
 
    return localip;
}
 
void MainWindow::clientconnect()
{
    // 客户端连接
    ui->plainTextEdit_DispMsg->appendPlainText("**********客户端socket连接**********");
    ui->plainTextEdit_DispMsg->appendPlainText("**********peer address:"+
                                               tcpsocket->peerAddress().toString());
    ui->plainTextEdit_DispMsg->appendPlainText("**********peer port:"+
                                               QString::number(tcpsocket->peerPort()));
 
}
 
void MainWindow::clientdisconnect()
{
    // 客户端断开连接
    ui->plainTextEdit_DispMsg->appendPlainText("**********客户端socket断开连接**********");
    tcpsocket->deleteLater();
 
}
 
void MainWindow::socketreaddata()
{
    // 读取数据
    while(tcpsocket->canReadLine())
        ui->plainTextEdit_DispMsg->appendPlainText("[in]"+tcpsocket->readLine());
 
}
 
void MainWindow::newconnection()
{
    tcpsocket=tcpserver->nextPendingConnection();
 
    connect(tcpsocket,SIGNAL(connected()),this,SLOT(clientconnect()));
    clientconnect();
 
    connect(tcpsocket,SIGNAL(disconnected()),this,SLOT(clientdisconnect()));
 
    connect(tcpsocket,SIGNAL(readyRead()),this,SLOT(socketreaddata()));
 
    connect(tcpsocket,SIGNAL(stateChanged(QAbstractSocket::SocketState)),
            this,SLOT(OnSocketStateChanged(QAbstractSocket::SocketState)));
 
 
}
 
void MainWindow::closeEvent(QCloseEvent *event)
{
    if(tcpserver->isListening())
        tcpserver->close();
 
    event->accept();
}

2.客户端

UI绘图:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
 
#include <QMainWindow>
 
 
#include <QTcpSocket>
#include <QHostAddress>
#include <QHostInfo>
 
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
 
class MainWindow : public QMainWindow
{
    Q_OBJECT
 
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
 
private:
    Ui::MainWindow *ui;
 
 
private:
    QTcpSocket *tcpclient; // 客户端tcpclient
    QString getlocalip(); // 获取本机IP地址
 
protected:
    void closeEvent(QCloseEvent *event);
 
private slots:
    void connectfunc();
    void disconnectfunc();
    void socketreaddata();
 
 
 
 
 
    void on_pushButton_Connect_clicked();
    void on_pushButton_Send_clicked();
    void on_pushButton_Disconnect_clicked();
};
#endif // MAINWINDOW_H

main.cpp

#include "mainwindow.h"
 
#include <QApplication>
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
 
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
 
    tcpclient=new QTcpSocket(this);
 
    QString strip=getlocalip();
 
    ui->comboBoxIp->addItem(strip);
 
 
    connect(tcpclient,SIGNAL(connected()),this,SLOT(connectfunc()));
    connect(tcpclient,SIGNAL(disconnected()),this,SLOT(disconnectfunc()));
    connect(tcpclient,SIGNAL(readyRead()),this,SLOT(socketreaddata()));
 
 
}
 
MainWindow::~MainWindow()
{
    delete ui;
}
 
 
void MainWindow::on_pushButton_Connect_clicked()
{
    QString addr=ui->comboBoxIp->currentText();
    quint16 port=ui->spinBoxPort->value();
    tcpclient->connectToHost(addr,port);
}
 
void MainWindow::on_pushButton_Send_clicked()
{
    QString strmsg=ui->lineEdit_InputMsg->text();
    ui->plainTextEdit_DispMsg->appendPlainText("[out]:"+strmsg);
    ui->lineEdit_InputMsg->clear();
 
    QByteArray str=strmsg.toUtf8();
    str.append('\n');
    tcpclient->write(str);
 
}
 
 
void MainWindow::on_pushButton_Disconnect_clicked()
{
    if(tcpclient->state()==QAbstractSocket::ConnectedState)
        tcpclient->disconnectFromHost();
}
 
 
 
 
QString MainWindow::getlocalip() // 获取本机IP地址
{
    QString hostname=QHostInfo::localHostName();
    QHostInfo hostinfo=QHostInfo::fromName(hostname);
 
    QString localip="";
 
    QList<QHostAddress> addlist=hostinfo.addresses();
    if(!addlist.isEmpty())
    {
        for (int i=0;i<addlist.count();i++)
        {
            QHostAddress ahost=addlist.at(i);
            if(QAbstractSocket::IPv4Protocol==ahost.protocol())
            {
                localip=ahost.toString();
                break;
            }
        }
    }
 
    return localip;
}
 
 
void MainWindow::closeEvent(QCloseEvent *event)
{
    if(tcpclient->state()==QAbstractSocket::ConnectedState)
    {
        tcpclient->disconnectFromHost();
    }
    event->accept();
 
}
 
 
void MainWindow::connectfunc()
{
    ui->plainTextEdit_DispMsg->appendPlainText("**********已经连接到服务器端**********");
    ui->plainTextEdit_DispMsg->appendPlainText("**********peer address:"+
                                               tcpclient->peerAddress().toString());
    ui->plainTextEdit_DispMsg->appendPlainText("**********peer port:"+
                                               QString::number(tcpclient->peerPort()));
 
    ui->pushButton_Connect->setEnabled(false);
    ui->pushButton_Disconnect->setEnabled(true);
 
}
void MainWindow::disconnectfunc()
{
    ui->plainTextEdit_DispMsg->appendPlainText("**********已断开与服务器端的连接**********");
 
    ui->pushButton_Connect->setEnabled(true);
    ui->pushButton_Disconnect->setEnabled(false);
 
}
void MainWindow::socketreaddata()
{
    while(tcpclient->canReadLine())
        ui->plainTextEdit_DispMsg->appendPlainText("[in]:"+tcpclient->readLine());
 
}

上位机通过网络编程与下位机实现通信

Qt作为上位机

51、32单片机或ARM开发板开作为下位机

通过网络编程实现通信

上位机可作为服务端或客户端,下位机也可作为服务端或客户端,具体按各自的项目需求实现

相关文章
|
7天前
|
域名解析 存储 网络协议
TCP套接字【网络】
TCP套接字【网络】
22 10
|
15天前
|
存储 机器人 Linux
Netty(二)-服务端网络编程常见网络IO模型讲解
Netty(二)-服务端网络编程常见网络IO模型讲解
|
20天前
|
网络协议 Python
告别网络编程迷雾!Python Socket编程基础与实战,让你秒变网络达人!
在网络编程的世界里,Socket编程是连接数据与服务的关键桥梁。对于初学者,这往往是最棘手的部分。本文将用Python带你轻松入门Socket编程,从创建TCP服务器与客户端的基础搭建,到处理并发连接的实战技巧,逐步揭开网络编程的神秘面纱。通过具体的代码示例,我们将掌握Socket的基本概念与操作,让你成为网络编程的高手。无论是简单的数据传输还是复杂的并发处理,Python都能助你一臂之力。希望这篇文章成为你网络编程旅程的良好开端。
37 3
|
1天前
|
JSON API 开发者
深入解析Python网络编程与Web开发:urllib、requests和http模块的功能、用法及在构建现代网络应用中的关键作用
深入解析Python网络编程与Web开发:urllib、requests和http模块的功能、用法及在构建现代网络应用中的关键作用
6 0
|
1月前
|
网络协议 C语言
C语言 网络编程(十三)并发的TCP服务端-以进程完成功能
这段代码实现了一个基于TCP协议的多进程并发服务端和客户端程序。服务端通过创建子进程来处理多个客户端连接,解决了粘包问题,并支持不定长数据传输。客户端则循环发送数据并接收服务端回传的信息,同样处理了粘包问题。程序通过自定义的数据长度前缀确保了数据的完整性和准确性。
|
1月前
|
网络协议 C语言
C语言 网络编程(十四)并发的TCP服务端-以线程完成功能
这段代码实现了一个基于TCP协议的多线程服务器和客户端程序,服务器端通过为每个客户端创建独立的线程来处理并发请求,解决了粘包问题并支持不定长数据传输。服务器监听在IP地址`172.17.140.183`的`8080`端口上,接收客户端发来的数据,并将接收到的消息添加“-回传”后返回给客户端。客户端则可以循环输入并发送数据,同时接收服务器回传的信息。当输入“exit”时,客户端会结束与服务器的通信并关闭连接。
|
1月前
|
网络协议 C语言
C语言 网络编程(十二)TCP通信创建-粘包
TCP通信中的“粘包”现象指的是由于协议特性,发送方的数据包被拆分并在接收方按序组装,导致多个数据包粘连或单个数据包分割。为避免粘包,可采用定长数据包或先传送数据长度再传送数据的方式。示例代码展示了通过在发送前添加数据长度信息,并在接收时先读取长度后读取数据的具体实现方法。此方案适用于长度不固定的数据传输场景。
|
1月前
|
网络协议
网络协议概览:HTTP、UDP、TCP与IP
理解这些基本的网络协议对于任何网络专业人员都是至关重要的,它们不仅是网络通信的基础,也是构建更复杂网络服务和应用的基石。网络技术的不断发展可能会带来新的协议和标准,但这些基本协议的核心概念和原理将继续是理解和创新网络技术的关键。
81 0
|
3月前
|
数据安全/隐私保护 C++ 计算机视觉
Qt(C++)开发一款图片防盗用水印制作小工具
文本水印是一种常用的防盗用手段,可以将文本信息嵌入到图片、视频等文件中,用于识别和证明文件的版权归属。在数字化和网络化的时代,大量的原创作品容易被不法分子盗用或侵犯版权,因此加入文本水印成为了保护原创作品和维护知识产权的必要手段。 通常情况下,文本水印可以包含版权声明、制作者姓名、日期、网址等信息,以帮助识别文件的来源和版权归属。同时,为了增强防盗用效果,文本水印通常会采用字体、颜色、角度等多种组合方式,使得水印难以被删除或篡改,有效地降低了盗用意愿和风险。 开发人员可以使用图像处理技术和编程语言实现文本水印的功能,例如使用Qt的QPainter类进行文本绘制操作,将文本信息嵌入到图片中,
149 1
Qt(C++)开发一款图片防盗用水印制作小工具
|
2月前
|
监控 C++ 容器
【qt】MDI多文档界面开发
【qt】MDI多文档界面开发
52 0

推荐镜像

更多