当前位置: 首页> 财经> 产业 > 【QT】TCP

【QT】TCP

时间:2025/8/26 8:21:36来源:https://blog.csdn.net/lzb_kkk/article/details/140545540 浏览次数:0次

目录

核心API

示例:服务器和客户端信息互发

服务器代码实现

第一步:创建QTcpServer对象的实例

第二步:绑定信号槽,处理新的连接

第三步:绑定并监听端口号

客户端代码实现

第一步:创建socket对象的实例

第二步:和服务器建立连接

第三步:连接信号槽,处理响应 

第四步:等待连接结果,确认是否连接成功 

最终效果


UDP 无连接,不可靠传输,面向数据包,全双工

TCP 有连接,可靠传输,面向字节流,半双工

核心API

核心类是两个: QTcpServer QTcpSocket

QTcpServer ⽤于监听端⼝, 和获取客户端连接

名称
类型
说明
对标原⽣ API
listen(const QHostAddress&, quint16 port)
⽅法
绑定指定的地址和端⼝号, 并开始监听
bind 和 listen
nextPendingConnection()
⽅法
从系统中获取到⼀个已经建⽴好的 tcp 连接.
返回⼀个 QTcpSocket , 表⽰这个
客⼾端的连接.
通过这个 socket 对象完成和客⼾端 之间的通信
accept
newConnection
信号
有新的客⼾端建⽴连接好之后触发.
⽆ (但是类似于 IO 多路复⽤
中的通知机制)
QTcpSocket 用户客⼾端和服务器之间的数据交互
名称类型说明对标原⽣ API
readAll()
⽅法
读取当前接收缓冲区中的所有数据.
返回 QByteArray 对象.
read
write(const QByteArray& )
⽅法
把数据写⼊ socket 中.
write
deleteLater
⽅法
暂时把 socket 对象标记为⽆效. Qt
会在下个事件循环中析构释放该对
象.
⽆ (但是类似于 "半⾃动化的 垃圾回收")
readyRead
信号
有数据到达并准备就绪时触发
⽆ (但是类似于 IO 多路复⽤
中的通知机制)
disconnected
信号
连接断开时触发
⽆ (但是类似于 IO 多路复⽤
中的通知机制)

示例:服务器和客户端信息互发

服务器代码实现

首先区分QTcpServer 和 QTcpSocket,我们需要先使用QTcpServer来监听端⼝, 和获取客户端连接。

第一步:创建QTcpServer对象的实例

tcpServer = new QTcpServer(this代码);

第二步:绑定信号槽,处理新的连接

connect(tcpServer,&QTcpServer::newConnection,this,&Widget::processConnection);

processConnection方法 

void Widget::processConnection()

{

    //1.通过tcpserver拿到一个socket对象,通过这个对象来和客户端进行通信

    QTcpSocket* clientSocket = tcpServer->nextPendingConnection();

    QString log = "[" + clientSocket->peerAddress().toString() + ":" +QString::number(clientSocket->peerPort()) + " 客户端上线了!";

    ui->listWidget->addItem(log);

    //2.通过信号槽,来处理客户端发来请求的情况

    connect(clientSocket,&QTcpSocket::readyRead,this,[=](){

       // a) 读取请求数据,此处readAll返回的是QByteArray,通过赋值转成 QString

       QString request = clientSocket->readAll();

       // b) 根据请求处理响应

       const QString& response = process(request);

       // c) 把响应写回到客户端

       clientSocket->write(response.toUtf8());

       // d) 把上述信息记录到日志中

       QString log = "[" + clientSocket->peerAddress().toString() + ":" + QString::number(clientSocket->peerPort()) + "]" + "req:" + request + ",resp:" + response;

    });

       ui->listWidget->addItem(log);

    //3. 通过信号槽,来处理客户端断开连接的情况

    connect(clientSocket,&QTcpSocket::disconnected,this,[=](){

        //a) 把断开连接的信息通过日志显示出来

       QString log = "[" + clientSocket->peerAddress().toString() + ":" +QString::number(clientSocket->peerPort()) + " 客户端下线了!";

       ui->listWidget->addItem(log);

       //b) 手动释放clientSocket

       clientSocket->deleteLater();

    });

}

注意: 

  • 在Linux网络编程中,需要搞一个循环,循环的读取请求,循环的处理,在Qt中基于信号槽就不必循环了。每次客户端发来请求,都能触发readyRead信号。
  • 因为QTcpSocket是每个客户端都有一个这样的对象,存在n个,所以必须在客户端断开连接后手动释放,而QTcpServer和QUdpSocket只有一份
  • clientSocket->deleteLater();这个操作,不是立即销毁clientSocket,而是告诉Qt,下一轮事件循环时,再进行销毁操作。

第三步:绑定并监听端口号

    bool ret = tcpServer->listen(QHostAddress::Any,9090);

    if(!ret)

    {

        QMessageBox::critical(this,"服务器启动失败!",tcpServer->errorString());

        exit(1);

    }

完整代码:

widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QTcpServer>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();void processConnection();QString process(const QString request);
private:Ui::Widget *ui;QTcpServer* tcpServer;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>
#include <QTcpSocket>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//修改窗口标题this->setWindowTitle("服务器");//2.创建QTcpServer的实例tcpServer = new QTcpServer(this);//3.通过信号槽,指定如何处理连接connect(tcpServer,&QTcpServer::newConnection,this,&Widget::processConnection);//4.绑定并监听端口号bool ret = tcpServer->listen(QHostAddress::Any,9090);if(!ret){QMessageBox::critical(this,"服务器启动失败!",tcpServer->errorString());exit(1);}
}Widget::~Widget()
{delete ui;
}void Widget::processConnection()
{//1.通过tcpserver拿到一个socket对象,通过这个对象来和客户端进行通信QTcpSocket* clientSocket = tcpServer->nextPendingConnection();QString log = "[" + clientSocket->peerAddress().toString() + ":" +QString::number(clientSocket->peerPort()) + " 客户端上线了!";ui->listWidget->addItem(log);//2.通过信号槽,来处理客户端发来请求的情况connect(clientSocket,&QTcpSocket::readyRead,this,[=](){// a) 读取请求数据,此处readAll返回的是QByteArray,通过赋值转成 QStringQString request = clientSocket->readAll();// b) 根据请求处理响应const QString& response = process(request);// c) 把响应写回到客户端clientSocket->write(response.toUtf8());// d) 把上述信息记录到日志中QString log = "[" + clientSocket->peerAddress().toString() + ":" + QString::number(clientSocket->peerPort()) + "]" + "req:" + request + ",resp:" + response;ui->listWidget->addItem(log);});//3. 通过信号槽,来处理客户端断开连接的情况connect(clientSocket,&QTcpSocket::disconnected,this,[=](){//a) 把断开连接的信息通过日志显示出来QString log = "[" + clientSocket->peerAddress().toString() + ":" +QString::number(clientSocket->peerPort()) + " 客户端下线了!";ui->listWidget->addItem(log);//b) 手动释放clientSocketclientSocket->deleteLater();});
}QString Widget::process(const QString request)
{return request;
}

客户端代码实现

客户端不需要跟服务器一样监听端口,因此只需要创建socket即可

第一步:创建socket对象的实例

 tcpSocket = new QTcpSocket(this);

第二步:和服务器建立连接

 这个函数不会阻塞等待三次握手完成的(非阻塞函数)

tcpSocket->connectToHost("127.0.0.1",9090);

第三步:连接信号槽,处理响应 

 connect(tcpSocket,&QTcpSocket::readyRead,this,[=](){

       QString response = tcpSocket->readAll();

        ui->listWidget->addItem("服务器说:"+response);

    });

第四步:等待连接结果,确认是否连接成功 

    bool ret = tcpSocket->waitForConnected();

    if(!ret){

        QMessageBox::critical(this,"连接服务器",tcpSocket->errorString());

    }

完整代码: 

 widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QTcpSocket>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void on_pushButton_clicked();private:Ui::Widget *ui;QTcpSocket* tcpSocket;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//1.设置窗口标题this->setWindowTitle("客户端");//2.创建socket对象的实例tcpSocket = new QTcpSocket(this);//3.和服务器建立连接  这个函数不会阻塞等待三次握手完成的(非阻塞函数)tcpSocket->connectToHost("127.0.0.1",9090);//4. 连接信号槽,处理响应connect(tcpSocket,&QTcpSocket::readyRead,this,[=](){QString response = tcpSocket->readAll();ui->listWidget->addItem("服务器说:"+response);});//5.等待连接建立的结果,确认是否连接成功bool ret = tcpSocket->waitForConnected();if(!ret){QMessageBox::critical(this,"连接服务器",tcpSocket->errorString());}
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_clicked()
{//1.获取输入的内容const QString& text = ui->lineEdit->text();//2.发送数据给服务器tcpSocket->write(text.toUtf8());//3.把发送的信息显示到界面上ui->listWidget->addItem("客户端说:" + text);//4.清空输入框的内容ui->lineEdit->setText("");}

最终效果

关键字:【QT】TCP

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: