Bootstrap

【qt】 TCP编程小项目

话不多说,先一睹芳颜
在这里插入图片描述

一.服务端

1.界面设计

在这里插入图片描述

2.服务端获取主机地址

在这里插入图片描述

将主机地址放在了一个容器中.
在这里插入图片描述

3.初始化服务端

在这里插入图片描述
当有新的客户端请求连接时,会发出newConnection()的信号.

4.服务端开启监听

在这里插入图片描述
注意listen函数的参数类型,要转换一下.

5.套接字socket

当有客户端请求连接后,我们需要套接字来作为服务端和客户端的接口.
在这里插入图片描述

6.服务端的读写

当有信息可以读的时候,我们就可以来读信息.
在这里插入图片描述
在这里插入图片描述
发送信息用write,注意要用utf8编码.
在这里插入图片描述

7.socket的其他信号的槽函数

在这里插入图片描述

8.服务端关闭监听

在这里插入图片描述

9.完整代码

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
#include <QHostInfo>
#include <QHostAddress>
#include <QLabel>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_pushButtonOpen_clicked();

    void on_pushButtonClose_clicked();

    void onNewConnection();

    void onReadyRead();

    void onConnected();

    void onDisconnected();

    void onStateChanged(QAbstractSocket::SocketState socketState);

private:
    Ui::MainWindow *ui;

    QTcpServer *tcpServer;
    QTcpSocket *tcpSocket;
    QStringList addrs;
    QLabel *labelState;


    void initTCPServer();
    void getHostAddress();
    void sendMsg(const QString&str);
    void initLabel();
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>

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

    initTCPServer();
    initLabel();

}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButtonOpen_clicked()
{
    getHostAddress();
    int i=rand()%addrs.count();
    QString addr=addrs.at(i);
    ui->labelIP->setText("服务器地址:"+addr);
    quint16 port=rand()%9000+8000;
    ui->labelPort->setText("服务器端口:"+QString::number(port));
    QHostAddress IP(addr);
    tcpServer->listen(IP,port);

    ui->pushButtonOpen->setEnabled(false);
    ui->pushButtonClose->setEnabled(true);
    ui->labelIP->show();
    ui->labelPort->show();
}

void MainWindow::on_pushButtonClose_clicked()
{
    if(tcpServer->isListening())
    {
        tcpServer->close();
        ui->pushButtonOpen->setEnabled(true);
        ui->pushButtonClose->setEnabled(false);
        ui->labelIP->hide();
        ui->labelPort->hide();
    }
}

void MainWindow::onNewConnection()
{
    tcpSocket=tcpServer->nextPendingConnection();
    connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(onReadyRead()));
    connect(tcpSocket,SIGNAL(connected()),this,SLOT(onConnected()));
    connect(tcpSocket,SIGNAL(disconnected()),this,SLOT(onDisconnected()));
    connect(tcpSocket,SIGNAL(stateChanged(QAbstractSocket::SocketState socketState)),
            this,SLOT(onStateChanged(QAbstractSocket::SocketState)));
    onStateChanged(tcpSocket->state());
}


void MainWindow::onReadyRead()
{
    QString str;
    while(tcpSocket->canReadLine())
    {
        QString read=tcpSocket->readLine();
        //qDebug()<<tcpSocket->readLine()<<endl;
        if(read=="人有悲欢离合\n")
        {
            str="月有阴晴圆缺";
            sendMsg(str);
        }
        else if(read=="此情可待成追忆\n")
        {
            str="只是当时已惘然";
            sendMsg(str);
        }
        else if(read=="宁教我负天下人\n")
        {
            str="休教天下人负我";
            sendMsg(str);
        }
        else
        {
            str="喂喂喂!你在说啥?";
            sendMsg(str);
        }
    }
}

void MainWindow::onConnected()
{
    labelState->setText("连接状态: 已连接");
}

void MainWindow::onDisconnected()
{
    labelState->setText("连接状态: 已断开连接");
    tcpSocket->deleteLater();//之后删
}

void MainWindow::onStateChanged(QAbstractSocket::SocketState socketState)
{
    switch (socketState) {
    case QAbstractSocket::UnconnectedState:
        labelState->setText("连接状态: 已断开连接");
        break;
    case QAbstractSocket::ConnectedState:
        labelState->setText("连接状态: 已连接");
        break;
    }
}

void MainWindow::initTCPServer()
{
    tcpServer=new QTcpServer(this);
    connect(tcpServer,SIGNAL(newConnection()),this,SLOT(onNewConnection()));
}

void MainWindow::getHostAddress()
{
    QHostInfo hostInfo =QHostInfo::fromName(QHostInfo::localHostName());
    QList<QHostAddress> lists=hostInfo.addresses();
    for(int i=0;i<lists.count();i++)
    {
        QHostAddress address=lists[i];
        if(address.protocol()==QAbstractSocket::IPv4Protocol)
        {
            addrs.append(address.toString());
        }
    }
}

void MainWindow::sendMsg(const QString &str)
{
    QByteArray msg= str.toUtf8();
    msg.append('\n');
    tcpSocket->write(msg);
}

void MainWindow::initLabel()
{
    labelState=new QLabel("连接状态: 未连接");
    ui->statusbar->addWidget(labelState);
    ui->labelIP->hide();
    ui->labelPort->hide();

    QLinearGradient gradient(0,0,ui->label->width(),ui->label->height());
    gradient.setColorAt(0,Qt::green);
    gradient.setColorAt(1,Qt::blue);

    QPalette palette;
    palette.setBrush(QPalette::WindowText,QBrush(gradient));
    ui->label->setPalette(palette);
}

二.客户端

1.界面设计

在这里插入图片描述

2.套接字的初始化

在这里插入图片描述

3.连接服务器

在这里插入图片描述
如果连接成功,就弹出我们的发送框.
在这里插入图片描述

这里的tcpSocketGet是在对话框中获取到套接字的,然后可以来发送信息.
在这里插入图片描述

4.界面设计师类

在这里插入图片描述
在这里插入图片描述

5.客户端的读写

在这里插入图片描述
读到的信息添加到对话框中.
在这里插入图片描述
发送信息:
在这里插入图片描述
发送的信息都添加了一个换行符,因为这样可以判断一行,然后对方进行读取.

6.客户端关闭连接

在这里插入图片描述

7.完整代码

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTcpSocket>
#include <QHostAddress>
#include <QLabel>
#include <dialog.h>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_pushButtonConnect_clicked();

    void on_pushButtonDisConnect_clicked();

    void onConnected();

    void onDisconnected();

    void onReadyRead();

private:
    Ui::MainWindow *ui;

    QTcpSocket*tcpSocket;

    QLabel* labState;
    QLabel* labIP;
    QLabel* labPort;
    Dialog* chat;


    void initTCPSocket();
    void intitLabel();
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

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

    initTCPSocket();
    intitLabel();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::initTCPSocket()
{
    tcpSocket=new QTcpSocket(this);
    connect(tcpSocket,SIGNAL(connected()),this,SLOT(onConnected()));
    connect(tcpSocket,SIGNAL(disconnected()),this,SLOT(onDisconnected()));
    connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(onReadyRead()));

}

void MainWindow::intitLabel()
{
    labState=new QLabel(this);
    labState->setMinimumWidth(100);
    labPort=new QLabel(this);
    labPort->setMinimumWidth(100);
    labIP=new QLabel(this);
    this->statusBar()->addWidget(labState);
    this->statusBar()->addWidget(labPort);
    this->statusBar()->addWidget(labIP);
}


void MainWindow::on_pushButtonConnect_clicked()
{
    QString addr=ui->lineEditAddr->text();
    QString port=ui->lineEditProt->text();
    if(addr==NULL||port==NULL)return;
    QHostAddress IP(addr);
    tcpSocket->connectToHost(IP,port.toInt());
}

void MainWindow::on_pushButtonDisConnect_clicked()
{
    if(tcpSocket->state()==QAbstractSocket::ConnectedState)
    {
        tcpSocket->disconnectFromHost();
        chat->close();
    }
}

void MainWindow::onConnected()
{
    labState->setText("连接状态: 已连接");
    labPort->setText("服务器端口: "+QString::number(tcpSocket->peerPort()));
    labIP->setText("服务器IP: "+tcpSocket->peerAddress().toString());
    chat=new Dialog(this);
    //this->hide();
    chat->tcpSocketGet(tcpSocket);
    chat->show();
}

void MainWindow::onDisconnected()
{
    labState->setText("连接状态: 已断开连接");
    labState->clear();
    labIP->clear();
    labPort->clear();
}


void MainWindow::onReadyRead()
{
    while(tcpSocket->canReadLine())
    {
        QString str=tcpSocket->readLine();
        chat->setMsg(str);
    }
}

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QTcpSocket>

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = nullptr);
    ~Dialog();

    void setMsg(const QString&str);
    void tcpSocketGet(QTcpSocket *tcpSocket);

private slots:
    void on_pushButton_clicked();

private:
    Ui::Dialog *ui;
    QTcpSocket*tcpSocket;


protected:
    void closeEvent(QCloseEvent*event);

};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"
#include <QDebug>
#include <QHostAddress>

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    ui->plainTextEdit->setReadOnly(true);
}

Dialog::~Dialog()
{
    delete ui;
}

void Dialog::setMsg(const QString &str)
{
    ui->plainTextEdit->appendPlainText("服务器: "+str);
}

void Dialog::tcpSocketGet(QTcpSocket *tcpSocket)
{
    this->tcpSocket=tcpSocket;
    //qDebug()<<this->tcpSocket->peerAddress();
}

void Dialog::on_pushButton_clicked()
{
    QString str=ui->lineEdit->text();
    QByteArray msg=str.toUtf8();
    msg.append('\n');
    tcpSocket->write(msg);
    ui->plainTextEdit->appendPlainText("客户: "+str);
    ui->lineEdit->clear();
    ui->lineEdit->setFocus();
}

void Dialog::closeEvent(QCloseEvent *event)
{
    if(tcpSocket->state()==QAbstractSocket::ConnectedState)
    {
        tcpSocket->disconnectFromHost();
    }

    event->accept();
}

三.结语

当然我这里只是稍微的演示一下,你也可以自己在服务端做手脚,自己发送信息也可以.

念头通达,现在应该算是炼气期1层.

;