基于QT制作一个TCPServer与TCPClient的通信

 更新时间:2023年12月26日 08:42:13   作者:澄澈i  
这篇文章主要为大家详细介绍了如何基于QT制作一个TCPServer与TCPClient的通信,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下

前言

之前项目上用到了TCP通信,作为TCP的服务端上位机与下位机进行控制信号传输。

这篇博客就对QT中使用TCP通信理一个简单的demo,做一个简单的TCP服务端和客户端的通信。

因为时间有限,这里就阐述一下基本原理和代码实现,具体的demo参考的是《QT5.9C++开发指南》

具体效果图如下

1. TCP通信原理和流程阐述

1.1 TCP 通信原理简述

TCP通信主要是三次握手和四次挥手,前者是建立连接,后者是断开连接。

上图是三次握手的一个基本流程图:

首先客户机向服务器申请同步,即向服务器申请连接。

服务器接收到请求,返回一个确认帧,告诉客户机已经收到你的请求,同意连接。

客户机收到同意请求信息之后,还要告诉服务器它已经收到服务器的确认请求,接下来可以传输数据。

上面是一个简单的TCP建立连接的阐述,那么回归到服务器端。在QT中,TCP服务器端使用QTcpServer用于端口监听和建立服务器,服务器和客户端之间在建立连接后,通信使用QTcpSocket,套接字Socket进行。

1.2 TCP服务端建立与通信流程

在QT中,使用QTcpServer::listen()函数开始服务器端监听,这里可以指定监听的IP地址和端口。这个表示服务器的IP和端口,监听向这个IP和端口发起请求的客户端。

当有新的客户端接入时,QTcpServer内部的incomingConnection()函数会创建一个与客户端连接的QTcpSocket对象,接着发射信号newConnection()。在newConnection()信号的槽函数中,可以用nextPendingConnection()接收客户端的连接,最后使用QTcpSocket与客户端通信。

1.3 TCP客户端通信流程

TCP客户端使用QTcpSocket与TCP服务器建立连接并通信。

客户端的QTcpSocket 实例首先通过 connectToHost()尝试连接到服务器,需要指定服务器的IP 地址和端口。

connectToHost()是异步方式连接服务器,不会阻塞程序运行,连接后发射 connected()信号。

如果需要使用阻塞方式连接服务器,则使用 waitForConnected()函数阻塞程序运行,直到连接成功或失败。
例如:

socket->connectToHost("192.168.1.100",1340);
    if(socket->waitForConnected(1000)
        qDebug("Connected!");

客户端与服务器建立socket连接后,就可以向缓冲区写数据或从接收缓冲区读取数据,实现数据的通信。当缓冲区有新数据进入时,会发射readyRead()信号,一般在此信号的槽函数里面读取缓冲区数据。

2. 关键源码阐述

2.1 服务端代码

初始化TCP服务端,绑定信号与槽函数

    QTcpServer *tcpServer; //TCP服务器
    QTcpSocket *tcpSocket;//TCP通讯的Socket

    tcpServer=new QTcpServer(this);
    connect(tcpServer,SIGNAL(newConnection()),this,SLOT(onNewConnection()));

定义了一个TcpServer的对象tcpServer,将获取的newConnection()信号绑定到自定义的槽函数onNewConnection()上。

开始监听,选择IP和端口号

void MainWindow::on_actStart_triggered()
{//开始监听
    QString     IP=ui->comboIP->currentText();//IP地址
    quint16     port=ui->spinPort->value();//端口
    QHostAddress    addr(IP);
    tcpServer->listen(addr,port);//指定ip和端口,这里的IP就是默认IP端口也是控件的默认值端口
//    tcpServer->listen(QHostAddress::LocalHost,port);// Equivalent to QHostAddress("127.0.0.1").
    ...
    ...
}

下面这个函数绑定了一些tcp连接的状态信号和对应的处理函数。

对于接收到的tcpServer连接,使用nextPending函数创建socket进行通信。

void MainWindow::onNewConnection()
{
//    ui->plainTextEdit->appendPlainText("有新连接");
    tcpSocket = tcpServer->nextPendingConnection(); //创建socket

    connect(tcpSocket, SIGNAL(connected()),
            this, SLOT(onClientConnected()));
    onClientConnected();//

    connect(tcpSocket, SIGNAL(disconnected()),
            this, SLOT(onClientDisconnected()));

    connect(tcpSocket,SIGNAL(stateChanged(QAbstractSocket::SocketState)),
            this,SLOT(onSocketStateChange(QAbstractSocket::SocketState)));
    onSocketStateChange(tcpSocket->state());

    connect(tcpSocket,SIGNAL(readyRead()),
            this,SLOT(onSocketReadyRead()));
}

服务端发送数据函数:

void MainWindow::on_btnSend_clicked()
{//发送一行字符串,以换行符结束
    QString  msg=ui->editMsg->text();
    ui->plainTextEdit->appendPlainText("[out] "+msg);
    ui->editMsg->clear();
    ui->editMsg->setFocus();

    QByteArray  str=msg.toUtf8();
    str.append('\n');//添加一个换行符
    tcpSocket->write(str);
}

服务器读取数据

void MainWindow::onSocketReadyRead()
{//读取缓冲区行文本
//    QStringList   lines;
    while(tcpSocket->canReadLine())
        ui->plainTextEdit->appendPlainText("[in] "+tcpSocket->readLine());
//        lines.append(clientConnection->readLine());
}

2.2 客户端代码

对于客户端来说主要是socket通信

初始化客户端并绑定信号

    QTcpSocket  *tcpClient;  //socket
 	tcpClient=new QTcpSocket(this); //创建socket变量
     connect(tcpClient,SIGNAL(connected()),this,SLOT(onConnected()));
    connect(tcpClient,SIGNAL(disconnected()),this,SLOT(onDisconnected()));

    connect(tcpClient,SIGNAL(stateChanged(QAbstractSocket::SocketState)),
            this,SLOT(onSocketStateChange(QAbstractSocket::SocketState)));
    connect(tcpClient,SIGNAL(readyRead()),
            this,SLOT(onSocketReadyRead()));

连接到服务器

    QString     addr=ui->comboServer->currentText();
    quint16     port=ui->spinPort->value();
    tcpClient->connectToHost(addr,port);

发送数据

void MainWindow::on_btnSend_clicked()
{//发送数据
    QString  msg=ui->editMsg->text();
    ui->plainTextEdit->appendPlainText("[out] "+msg);
    ui->editMsg->clear();
    ui->editMsg->setFocus();

    QByteArray  str=msg.toUtf8();
    str.append('\n');
    tcpClient->write(str);
}

读取数据

void MainWindow::onSocketReadyRead()
{//readyRead()信号槽函数
    while(tcpClient->canReadLine())
        ui->plainTextEdit->appendPlainText("[in] "+tcpClient->readLine());
}

以上就是基于QT制作一个TCPServer与TCPClient的通信的详细内容,更多关于QT TCP通信的资料请关注脚本之家其它相关文章!

相关文章

  • C/C++语言中结构体的内存分配小例子

    C/C++语言中结构体的内存分配小例子

    当未用 #pragma 指令指定编译器的对齐位数时,结构体按最长宽度的数据成员的宽度对齐;当使用了 #pragma 指令指定编译器的对齐位数时,结构体按最长宽度的数据成员的宽度和 #pragma 指令指定的位数中的较小值对齐
    2013-10-10
  • C语言之把数组名作函数参数的四种情况说明

    C语言之把数组名作函数参数的四种情况说明

    这篇文章主要介绍了C语言之把数组名作函数参数的四种情况说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • C++有符号和无符号之间的转换问题

    C++有符号和无符号之间的转换问题

    在开发中经常会遇到有符号和无符号之间的转换问题,如果不清楚问题根源,很难解决bug,今天小编通过本文给大家分享c++有符号无符号转换问题,需要的朋友参考下
    2021-07-07
  • Opencv 视频读取与写入的实现示例

    Opencv 视频读取与写入的实现示例

    本文将介绍如何使用OpenCV进行视频读写。通过阅读本文,您将了解如何读取视频文件、处理视频帧、写入视频文件等操作,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
    2023-08-08
  • C++ ReSharper2021激活码永久有效

    C++ ReSharper2021激活码永久有效

    ReSharperC++是为c/c++开发者打造的一款实用Visual Studio扩展插件,这款插件旨在提升开发者的效率,今天给大家分享这款软件的激活方法,需要C++ ReSharper2021激活码的朋友参考下本文
    2021-06-06
  • C语言中的for循环语句基本语法及使用

    C语言中的for循环语句基本语法及使用

    这篇文章主要介绍了C语言中的for循环语句基本语法及使用,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-06-06
  • C语言编程题杨氏矩阵算法快速上手示例详解

    C语言编程题杨氏矩阵算法快速上手示例详解

    这篇文章主要为大家介绍了C语言编程题杨氏矩阵算法快速上手的示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2021-10-10
  • C语言实现三子棋游戏含完整代码

    C语言实现三子棋游戏含完整代码

    本文详细讲解了C语言实现三子棋游戏内含完整代码,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-11-11
  • C++生成随机数的实现代码

    C++生成随机数的实现代码

    这篇文章主要介绍了C++生成随机数的实现代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-04-04
  • 使用C语言构建基本的二叉树数据结构

    使用C语言构建基本的二叉树数据结构

    这篇文章主要介绍了使用C语言使用C语言构建基本的二叉树数据结构,包括根据前序序列和中序序列构建二叉树的方法,需要的朋友可以参考下
    2015-08-08

最新评论