Qt::聊天小程序——基于TCP的半双工通信

本次要实现的是一个基于TCP的聊天程序,客户端输入服务器端的IP地址和端口号,在客户端发送消息,服务器端可以接收,服务器端发送消息,客户端也可以接收

通信过程

基于TCP的半双工通信

先写服务端代码
服务器
头文件:dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QTcpServer>
#include <QDateTime>
#include <QTcpSocket>
#include <QTextStream>
#include <QMessageBox>
namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

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

private:
    Ui::Dialog *ui;
    QTcpServer * server;// 管理类对象
    QTcpSocket * socket = NULL;// 连接类对象,只能连接一个对象,多个对象连接一个服务器需要创建QList类
private slots:
    void newConnSlot();// 新连接建立的槽函数
    void disConnSlot();// 网络连接断开的槽函数
    void readyReadSlot();// 读取消息的槽函数
    void btnSndMsgClickedSlot();// 发送信息的槽函数
};

#endif // DIALOG_H

源文件:dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    setWindowFlags(Qt::WindowStaysOnTopHint);// 设置窗口标记为顶层
    server = new QTcpServer(this);// 创建管理类对象
    connect(server,SIGNAL(newConnection()),this,SLOT(newConnSlot()));// 连接服务器通知的信号槽
    // 服务器开启监听,等待客户主动发起连接
    // 参数1:监听来自于哪个IP地址的请求,默认值Any:不限制IP地址,QHostAddress类是IP地址的封装类。
    // 参数2:服务器端口号
    server->listen(QHostAddress::Any,8877);
}

Dialog::~Dialog()
{
    if(server->isListening()){// 如果还在监听,则关闭
        server->close();
    }
    delete ui;
}

void Dialog:: newConnSlot()
{
    if(socket != NULL){// 如果不是第一次连接服务器,先踢掉之前的连接
        socket->close();
    }
    socket = server->nextPendingConnection();// 拿到与客户端进行连接的QTcpSocket对象
    connect(socket,SIGNAL(disconnected()),this,SLOT(disConnSlot()));// 建立断链通知的信号槽
    connect(socket,SIGNAL(readyRead()),this,SLOT(readyReadSlot()));// 建立读取消息的信号槽

    connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(btnSndMsgClickedSlot()));// 建立发送消息的信号槽

    QString ip = socket->peerAddress().toString();// 拿到对面客户端的IP与端口号
    qint16 port = socket->peerPort();
    QString time = QDateTime::currentDateTime().toString("hh:mm:ss");// 输出信息
    ui->textBrowser->append(time);
    ui->textBrowser->append("新客户连接");
    ui->textBrowser->append(ip.append(";").append(QString::number(port)));
    ui->textBrowser->append("");
}

void Dialog::disConnSlot()
{
    QString ip = socket->peerAddress().toString();// 拿到对面客户端的IP与端口号
    qint16 port = socket->peerPort();
    QString time = QDateTime::currentDateTime().toString("hh:mm:ss");
    ui->textBrowser->append(time);
    ui->textBrowser->append("客户已经断开连接");
    ui->textBrowser->append(ip.append(":").append(QString::number(port)));
    ui->textBrowser->append("");
}

void Dialog::readyReadSlot()
{
    QTextStream input(socket);
    QString msg = input.readLine();// 读取数据
    ui->textBrowser->append(msg);// 展示
}

void Dialog:: btnSndMsgClickedSlot()
{
    QString msg = ui->lineEdit->text();
    if(msg == ""){
        QMessageBox::warning(this,"warning","please input message!");
        return;
    }
    QTextStream outputTextBrower(socket);
    outputTextBrower<<msg.append("");
    ui->lineEdit->clear();
}

再写客户端代码
客户端
头文件:dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QTcpSocket>// 连接类
#include <QMessageBox>
#include <QTextStream>// 文本流类

#include <QTcpSocket>
namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

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

private:
    Ui::Dialog *ui;
    QTcpSocket *client;// 连接对象


private slots:
    void btnConnClickedSlot();
    void btnDisConnClickedSlot();
    void btnSndMsgClickedSlot();
    void connectedSlot();
    void disconnectSlot();

    void readyReadSlot();
};

#endif // DIALOG_H

源文件:dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    connect(ui->pushButtonConn,SIGNAL(clicked()),
            this,SLOT(btnConnClickedSlot()));
    connect(ui->pushButtonDisConn,SIGNAL(clicked()),
            this,SLOT(btnDisConnClickedSlot()));
    connect(ui->pushButtonSnd,SIGNAL(clicked()),this,SLOT(btnSndMsgClickedSlot()));
    setWindowFlags(Qt::WindowStaysOnTopHint);// 设置窗口标记为顶层
    client = new QTcpSocket(this);// 创建连接对象
    connect(client,SIGNAL(connected()),this,SLOT(connectedSlot()));// 连接状态检测的信号槽
    connect(client,SIGNAL(disconnected()),this,SLOT(disconnectSlot()));
}

Dialog::~Dialog()
{
    if(client->isOpen()){// 如果客户端还在连着,关掉
        client->close();
    }
    delete ui;
}

void Dialog:: btnConnClickedSlot()
{
	// 默认输入有效,连接到服务器
    // 参数1:服务器的IP地址
    // 参数2:服务器的端口号
    client->connectToHost(ui->lineEditIP->text(),ui->lineEditPor->text().toInt());
    connect(client,SIGNAL(readyRead()),this,SLOT(readyReadSlot()));
}

void Dialog::btnDisConnClickedSlot()
{
    client->close();
}

void Dialog::btnSndMsgClickedSlot()
{
    QString msg = ui->lineEdit->text();// 获取用户输入的内容
    if(msg == ""){
        QMessageBox::warning(this,"tip","please input message!");
        return ;
    }
    QTextStream output(client);// 创建文本流对象
    output<<msg;// 发送内容
    ui->lineEdit->clear();// 清空输入框

}

void Dialog:: connectedSlot()
{
    ui->lineEditIP->setEnabled(false);
    ui->lineEditPor->setEnabled(false);
    ui->pushButtonConn->setEnabled(false);// 屏蔽连接按钮
    ui->pushButtonConn->setText("已连接");
    ui->pushButtonSnd->setEnabled(true);// 释放发送按钮
    ui->lineEdit->setEnabled(true);
}

void Dialog::disconnectSlot()
{
    ui->lineEditIP->setEnabled(true);
    ui->lineEditPor->setEnabled(true);
    ui->pushButtonConn->setEnabled(true);// 恢复连接按钮
    ui->pushButtonConn->setText("连接");
    ui->pushButtonSnd->setEnabled(false);// 屏蔽发送按钮
    ui->lineEdit->setEnabled(false);
}

void Dialog:: readyReadSlot()
{
    QTextStream inputTextBrower(client);
    QString msg = inputTextBrower.readLine();
    ui->textBrowser->append(msg);
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值