QTcp 客户端与服务器端通信

QTcp 客户端与服务器端通信

思路
有一个服务器端QTcpServer 提供了一个端口号与IP ,使用listen时刻进行监听,有一个客户端QTcpClient 来连接该服务器,从而进行两者之间的通信,为了简化,通信的内容为纯文本格式。

界面如下:
QTcp 客户端与服务器端通信_第1张图片
QTcp 客户端与服务器端通信_第2张图片
客户端可以点击close按钮断开连接,服务器端也可以点击close按钮断开连接。在windows平台下使用QT5.9.8开发.

代码

                                 //serverwidget.cpp
#include "serverwidget.h"
#include "ui_serverwidget.h"
#include<QtDebug>

ServerWidget::ServerWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ServerWidget)
{
    ui->setupUi(this);

    tcpServer = NULL;
    tcpSocket = NULL;

    //监听套接字, 指定父对象 让他自动回收空间
    tcpServer =  new QTcpServer(this);

    tcpServer->listen(QHostAddress("127.0.0.2"),8888);      //这里只是设置了端口号 并没有设置IP地址  这个地址是可以的 但是设置其他的IP地址好像不行?
    setWindowTitle("服务器,端口:8888");



    //connect(sender, senderSignal, receiver, receiverSignal)
    //这里一旦连接成功 server 端会触发 由于不好说明客户端的操作 所以 这里以接受者服务器端建立newConnection 为准
    //一旦发现客户端的连接请求 就会发出newConnection信号 可以关联这个信号到我们自己的槽函数进行数据的发送
    connect(tcpServer, &QTcpServer::newConnection,
            [=]()
    {
        //取出建立好连接的套接字 这个才是真正的通信套接字
        tcpSocket = tcpServer->nextPendingConnection();

        //获取对方的IP 和端口
        QString ip = tcpSocket->peerAddress().toString();  //这里进行了强制转换
        ushort port = tcpSocket->peerPort();

        QString temp = QString("[%1:%2]:成功连接").arg(ip).arg(port);
        ui->textEditRead->setText(temp);   //在只读区域显示对方的IP和端口号


        //触发readyread 对对方发来的信息进行显示
        //在客户端 一旦有数据到来就会发出readyread()[建立连接需要握手 服务器端建立了连接 会发送数据到客户端]
        connect(tcpSocket, &QTcpSocket::readyRead,
                [=]()
        {
           QByteArray  array = tcpSocket ->readAll();
           //QByteArray  array =tcpSocket->readLine();
           ui->textEditRead->append(array);  //不覆盖 插入
           //ui->textEditRead->setText(array);  //会将之前的覆盖掉 重新写入
        }
        );


        connect(tcpSocket, &QTcpSocket::disconnected,
                [=]()
        {
            QString temp = QString("客户端主动断开连接");
            ui->textEditRead->setText(temp);
            tcpSocket->close();
        }
        );

//        if(tcpSocket->waitForConnected(1000) == false)
//        {
//            return;
//        }


    }

    );




}

ServerWidget::~ServerWidget()
{//delete tcpServer;
    //delete tcpSocket;
    delete ui;

}

void ServerWidget::on_ButtonSend_clicked()
{
    //服务器端发送内容
    //获取编辑区的内容 返回的是文本内容
    QString str = ui->textEditWrite->toPlainText();

    //开始发送了  使用tcpSocket套接字
    tcpSocket->write(str.toUtf8().data());

}

void ServerWidget::on_ButtonClose_clicked()
{

   tcpSocket->disconnectFromHost();
    //主动和客户端断开连接
   // tcpSocket->close();


    QString temp1 = QString("服务器主动断开连接");
    ui->textEditRead->setText(temp1);




}

                          //clientwidget.cpp
#include "clientwidget.h"
#include "ui_clientwidget.h"
#include<QHostAddress>

ClientWidget::ClientWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ClientWidget)
{
    ui->setupUi(this);
    setWindowTitle("客户端");
    tcpSocket = NULL;
    tcpSocket = new QTcpSocket(this);

    connect(tcpSocket, &QTcpSocket::connected,
            [=]()
    {
        ui->textEditRead->setText("成功和服务器建立好连接");

    }
            );
    connect(tcpSocket, &QTcpSocket::readyRead,
           [=]()
    {
        //获取对方发送的内容
        QByteArray array = tcpSocket->readAll();
        ui->textEditRead->append(array);

    }

            );

    /*
     *如果把下面的connect代码注释掉 就不会报错了 why??
     * */

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

        QString temp = QString("服务器已断开连接");
        ui->textEditRead->setText(temp);

    }
            );


}

ClientWidget::~ClientWidget()
{
    // delete tcpSocket;
    delete ui;

}

void ClientWidget::on_pushButton_clicked()
{
    //获取本地文本框中的端口 和IP
    QString ip = ui->lineEditIP->text();   //IP是以字符的形式进行存储
    int port = ui->lineEditPort->text().toInt();   //qint16 16位无符号整形数

    //主动和服务器建立连接
    tcpSocket->connectToHost(QHostAddress(ip),port);   //根据端口号和IP 地址与另外一台主机建立连接(这里另外一台主机就是服务器)

}


void ClientWidget::on_pushButtonSend_clicked()
{
    //获取编辑框内容
    QString str = ui->textEditWrite->toPlainText();   //以文本形式进行存储

    //发送数据 从str到tcpSocket
    tcpSocket->write(str.toUtf8().data());

}

void ClientWidget::on_pushButtonClose_clicked()
{
    //主动和服务器断开连接
    tcpSocket->disconnectFromHost();
    //tcpSocket->disconnect();

    ui->textEditRead->setText("主动与服务器断开连接");
    tcpSocket->close();



}

                               //main.cpp
#include "serverwidget.h"
#include <QApplication>
#include"clientwidget.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    ServerWidget w;
    w.show();

    ClientWidget w2;
    w2.show();
    return a.exec();
}

             //client.h
#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_pushButton_clicked();

    void on_pushButtonSend_clicked();

    void on_pushButtonClose_clicked();

private:
    Ui::ClientWidget *ui;
    QTcpSocket  *tcpSocket;
};

#endif // CLIENTWIDGET_H

                       //server.h
#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();

private slots:
    void on_ButtonSend_clicked();

    void on_ButtonClose_clicked();

private:
    Ui::ServerWidget *ui;

    QTcpServer *tcpServer;  //用指针 监听套接字
    QTcpSocket *tcpSocket;  //通信套接字


};

#endif // SERVERWIDGET_H

问题

程序可以正常运行,但是,在关闭的时候,如果直接关闭窗口的话,会提示运行错误。
在点击close关闭连接后,再关闭则没有这种错误。
目前尝试了使用**waitforConnect()**进行判断处理,但是好像没有效果。
目前还没有找到错误。

你可能感兴趣的:(QT学习)