QT入门(十五)——QT中使用TCP协议进行服务端与客户端的双向通信

效果图

在这里插入图片描述

一 .pro文件

添加network

QT       += core gui network

二 .h头文件中的定义

private slots:
    void on_pushButton_clicked();


    void on_pushButton_4_clicked();


    void on_pushButton_5_clicked();


    //客户端读取发送端发来的数据的槽函数
    void cread_data();


    void on_pushButton_2_clicked();


    //客户端点击 连接服务器,连接上会触发服务器发出newConnection的信号,进入receive_clien函数中
    void receive_client();


    //服务器读取客户端发来的数据的槽函数
    void sread_data();


    void on_pushButton_3_clicked();


    void on_pushButton_6_clicked();
private:
    Ui::MainWindow *ui;


    //客户端的套接字
    QTcpSocket  csocket;


    //声明一个QTcpserver的对象,用于监听
    QTcpServer sserver;
    //创建服务器的套接字,用于与客户端进行通信
    QTcpSocket *ssocket;

QTcpSocket *ssocket;服务器的套接字,用于与客户端进行通信。由于这个套接字是在服务器的receive-client这个槽函数中函数中获取的,又要在服务端的发送函数中使用,所以要变成全局变量。

三 .cpp中服务端的内容

1.启动服务器

服务端点击启动服务器,服务器就开始监听

//启动服务器
void MainWindow::on_pushButton_2_clicked()
{
     //监听----------启动服务器
    //QHostAddress::Any 地址,接纳所有的地址
    //端口号  ui->sportEdit->text()获得输入的字符串,转换成无符号短整型
    sserver.listen(QHostAddress::Any,ui->sportEdit->text().toUShort());
}

2.服务器现有新的连接时

当服务器发现有人要来连接时,就会发出newconnection 的信号,从而触发槽函数receive_client(自行编写的槽函数)
MainWindow::MainWindow(QWidget *parent) :里面添加connect关联函数

//客户端点击 连接服务器,连接上会触发服务器发出newConnection的信号,server进入new_client函数中
    //动作的发出者&sserver 服务器,发出的信号是newConnection
    //&QTcpServer中的这个函数newConnection会发出一个信号  动作的发出者是mserver服务器
    connect(&sserver,&QTcpServer::newConnection,this,&MainWindow::receive_client);

receive_client(自行编写的槽函数)

//建立接收客户端连接的槽函数,有人连接就触发这个槽函数
void MainWindow::receive_client()
{
    //获取这个服务器sserver与客户端通信的套接字
    ssocket=sserver.nextPendingConnection();
    //拿到套接字后,服务器可利用ssocket这个套接字中的write(),间接的向客户端发送数据,
    ssocket->write("connect");


    //客户端如有写入,就会触发readyread这个信号
    //关联一下客户端的写入信号,本来就是指针,不用取地址
    //写在这里是确保客户端连接了服务器
    //信号的发出者是ssocket 服务器与客户端之间通信的套接字
    //当有东西写入的时候,就会发出readyread的信号
    connect(ssocket,&QTcpSocket::readyRead,this,&MainWindow::sread_data);
}

关于 ssocket=sserver.nextPendingConnection();

想了很久,参考了其他的博客在这里插入图片描述
我是这么理解的
在sserver这个服务器的进程汇总,调用nextPendingConnection()这个函数,获得了一个QtcpSocket类型的指针,就是服务端的套接字,用来和客户端通信的,所以在后面的内容中,直接向ssocket里面写入内容,客户端就可以收到。但是返回的这个QtcpSocket类型的指针不可以用于另一个线程。

在接收到新客户的这个函数中,再定义一个connect,是确保客户端连接了服务器,信号的发出者是ssocket,发出的信号是准备读readyRead,触发服务器去执行sread_data这个槽函数。

3.服务器发现有数据进来时,要去读取数据

//槽函数
//服务器读取客户端csocket发来的数据的槽函数,然后显示在服务器端的stextBrowser中
void MainWindow::sread_data()
{
//    //获得信号的发送者的套接字
//    //sender()用于服务器获取客户端在发送内容的时候的套接字,其实获取到的内容就是sscoket
//    //dynamic_cast<QTcpSocket*> 将sender获得的内容强制转换成QTcpSocket*
//     QTcpSocket *msocket = dynamic_cast<QTcpSocket*>(sender());
//     //读取数据
//     QString msg = msocket->readAll();
//     //还可以读取对方的ip
//     QString ip =  msocket->peerAddress().toString();
//    //去掉前面的#ffff
//    ip.remove("::ffff:");


     QString msg = ssocket->readAll();
    QString ip =  ssocket->peerAddress().toString();


    //调用文本浏览框,显示内容
    ui->stextBrowser->append(ip+":"+msg);
}

服务器读取客户发来的信息的时候,也是要先获取发送者的套接字QTcpSocket *msocket = dynamic_cast<QTcpSocket*>(sender());赋值给msock,这个临时创建的套接字,然后从这个临时创建的套接字中读取信息,还可以读取ip

sender()函数,返回的是信号来源的对象,返回的就是,是谁进入了发出的信号,进入的这个槽函数。

4.服务端发送数据给客户端

//服务器端的 发送按钮  向客户端csocket写入数据
void MainWindow::on_pushButton_3_clicked()
{
    //获取数据  toPlainText()这个组件转字符串
    QString data = ui->stextEdit->toPlainText();
    ssocket->write(data.toUtf8());
}

由于ssocket是全局变量,所以上面在第三步中给它赋值了,这里就可以直接用了,直对它写入数据即可。

//服务器端的清空按钮
void MainWindow::on_pushButton_6_clicked()
{
    //清空一下textedit
    ui->stextEdit->clear();
}

四 .cpp中客户端的内容

1.客户端连接服务器

//client端的连接服务器按钮
void MainWindow::on_pushButton_clicked()
{
    // 根据输入的ip和port连接指定的服务器
     csocket.connectToHost(ui->cipEdit->text(),ui->cportEdit->text().toUShort());
     qDebug()<<"客户端连接服务器";
}

2.客户端向服务器发送内容

//client端 发送按钮
void MainWindow::on_pushButton_4_clicked()
{
    //获取数据  toPlainText()这个组件转字符串
    QString data = ui->ctextEdit->toPlainText();
    //向服务器发送数据,  转成字符数组
    csocket.write(data.toUtf8());
}
//client端 清空按钮
void MainWindow::on_pushButton_5_clicked()
{
    //清空一下textedit
    ui->ctextEdit->clear();
}

3.客户端接收内容

首先在MainWindow::MainWindow(QWidget *parent) :中建立connect连接

 //关联一下信号 作用是读取服务端发来的数据
    //当客户端发现有数据要进来的时候,就会发出readyread这个信号,触发读取并显示数据的槽函数    
    connect(&csocket,&QTcpSocket::readyRead,this,&MainWindow::cread_data);

槽函数

//client端的接收服务器发来的数据的槽函数
void MainWindow::cread_data()
{
    //通过套接字读取,保存服务器发过来的数据
    QString msg = csocket.readAll();
    //把数据放到文本浏览框中显示
    ui->ctextBrowser->append(msg);
}

小结

客户端和服务端一边一个套接字,服务器端还要加一个服务端的对象用于监听
客户端的套接字csocket(是一个变量)可以直接使用,但是服务端的套接字ssocket的赋值是在服务器对象监听到有东西来连接的时候,通过nextPendingConnection获得的,是一个指针。
服务器向客户端写东西:sscoket->write()
客户端向服务器写东西:cscoket.write()

读取服务器获得的内容ssocket->readAll();
读取客户端获得的内容 csocket.readAll();

  • 7
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Qt是一个跨平台的C++应用程序框架,它提供了丰富的库和工具来帮助开发者创建各种类型的应用程序,包括网络通信应用。 在Qt实现TCP服务端客户端的通信非常简单。首先,我们需要创建一个QTcpServer对象来作为服务端,该对象负责监听客户端的连接请求。接下来,我们需要为QTcpServer对象绑定一个IP地址和端口号,以便客户端能够连接到该地址和端口。当有新的客户端连接时,QTcpServer对象会发出newConnection()信号。 在服务端的槽函数,我们可以使用QTcpServer的nextPendingConnection()函数获取新连接的QTcpSocket对象,该对象用于和客户端进行通信。我们可以在该对象上发送和接收数据,以实现服务端客户端之间的数据交互。 接下来,我们需要创建一个QTcpSocket对象作为客户端,该对象负责和服务端建立连接。我们需要使用connectToHost()函数来指定要连接的服务端的IP地址和端口号。一旦连接成功,QTcpSocket对象会发出connected()信号。 在客户端的槽函数,我们可以使用QTcpSocket对象发送和接收数据。我们可以使用write()函数发送数据,使用readyRead()信号和read()函数接收数据。 通过这种方式,我们可以在服务端客户端之间进行双向的数据通信。服务端可以同时接受多个客户端的连接,每个客户端都可以和服务端进行独立的数据交互。 总的来说,使用Qt实现TCP服务端客户端通信非常方便。通过使用QTcpServer和QTcpSocket类,我们可以轻松地建立连接,发送和接收数据。这种通信方式可以应用于多种场景,如实时聊天、远程控制等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值