10.10 QT服务器与客户端
客户端
H文件
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QTcpSocket> //客户端类
#include <QMessageBox>
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_2_clicked();void connected_slot(); //定义处理connected信号的槽函数void readyRead_slot(); //定义处理readyRead信号的槽函数void on_pushButton_clicked();void on_pushButton_3_clicked();void disconnected_slot();private:Ui::Widget *ui;QTcpSocket *client; //客户端指针QString usernName; //储存用户名};
#endif // WIDGET_H
源文件
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//实例化一个客户端对象client = new QTcpSocket(this);//将客户端套接字的connectet的信号连接到自己的槽函数中connect(client,&QTcpSocket::connected,this,&Widget::connected_slot);//当服务器向客户端发来消息后,那么客户端套接字自动发射一个readRead信号//我们可以将信号连接到自定义的槽函数中处理相关逻辑connect(client,&QTcpSocket::readyRead,this,&Widget::readyRead_slot);//将disconnected信号连接到槽函数中connect(client,&QTcpSocket::disconnected,this,&Widget::disconnected_slot);}Widget::~Widget()
{delete ui;
}//连接服务器按钮对应的槽函数
void Widget::on_pushButton_2_clicked()
{//先获取ui界面上的数据usernName = ui->ten_name->text();QString ip =ui->ten_ip->text();quint16 port = ui->ten_port->text().toUInt();client->connectToHost(ip,port);//至此,表示已经向服务器发生连接请求了,如果成功连接服务器//那么该套接字就会自动发生一个connected的信号}
//自定义处理connected信号的槽函数
void Widget::connected_slot()
{QMessageBox::information(this,"提示","连接服务器成功");QString msg=usernName + "进入聊天室";//将消息发送给服务器client->write(msg.toLocal8Bit());
}
//之定义出来readyRead新号的曹函数的实现
void Widget::readyRead_slot()
{//读取套接字中的数据库QByteArray msg=client->readAll();//将消息展示到ui界面上ui->listWidget->addItem(QString::fromLocal8Bit(msg));
}//发消息对应的槽函数
void Widget::on_pushButton_clicked()
{//获取UI界面上的消息编辑器上的文本内容QString msg=usernName + ":"+ui->lineEdit->text();//将消息发送给服务器client->write(msg.toLocal8Bit());//清空编辑器的文本内容ui->lineEdit->clear();}//断开服务器按钮对应的槽函数
void Widget::on_pushButton_3_clicked()
{//向服务器发生 XXX:离开聊天室QString msg=usernName + ":离开聊天室";//将消息发给服务器client->write(msg.toLocal8Bit());//将套接字与服务器断开client->disconnectFromHost();//当客户端成功与服务器断开连接后,该客户端自动发一个disconneted的信号//
}void Widget::disconnected_slot()
{QMessageBox::information(this,"提示","断开连接");
}
服务器
h文件
#ifndef FWQ_H
#define FWQ_H#include <QWidget>
#include <QTcpServer>
#include <QList>
#include <QTcpSocket>
#include <QMessageBox>
#include <QDebug>QT_BEGIN_NAMESPACE
namespace Ui { class fwq; }
QT_END_NAMESPACEclass fwq : public QWidget
{Q_OBJECTpublic:fwq(QWidget *parent = nullptr);~fwq();private slots:void on_pushButton_clicked();void newconnetion_slots();void readyRead_slot();
private:Ui::fwq *ui;//定义服务器指针QTcpServer *server;//定义客户端QList<QTcpSocket *>clientlist;
};
#endif // FWQ_H
源文件
#include "fwq.h"
#include "ui_fwq.h"fwq::fwq(QWidget *parent): QWidget(parent), ui(new Ui::fwq)
{ui->setupUi(this);// 实例化服务器对象server=new QTcpServer(this);//将服务器的newconnetion信号连接到定义的槽函数中执行相关逻辑connect(server,&QTcpServer::newConnection,this,&fwq::newconnetion_slots);
}fwq::~fwq()
{delete ui;
}void fwq::on_pushButton_clicked()
{if(ui->pushButton->text()=="启动服务器"){//启动服务器//获取UI界面上的端口号quint16 port =ui->ten1->text().toUInt();//启动监听//函数原型:bool listen(const QHostAddress &address=QHosAddress::Any,quint10 port =0)//参数1:要监听的IP地址,HEostAddress::Any表示监听任意一台主机//参数2:服务器端口号,如果天0表示让系统自动分配端口号//返回值:成功返回监听返回值真(成功启动服务器) 否则返回假if(!server->listen(QHostAddress::Any,port)){QMessageBox::information(this,"提示","服务器启动失败");return ;}else{QMessageBox::information(this,"提示","服务器启动成功");}//程序执行到此,表示服务器启动成功了,此时如果有客户端向服务器发生连接请求,该服务器会自动发射一个newconnection信号//我们就可以将该信号连接到之定义的曹函数中执行逻辑,由于连接只需要一次,我们可以写在构造函数中//跟新按钮文件ui->pushButton->setText("关闭服务器");}else{//关闭服务器逻辑server->close();//跟新按钮文本内容ui->pushButton->setText("启动服务器");}
}
//处理newconnetion信号对应的槽函数定义
void fwq::newconnetion_slots()
{// QMessageBox::information(this,"提示","有新客户发来连接请求");qDebug()<<"有新客户端发来连接请求";//获取最新客户端的套接字QTcpSocket *s = server->nextPendingConnection();//该套接字放入到客户端链表中clientlist.push_back(s);//程序执行至此,一个服务器和多个客户端就已经建立了连接//当某个客户端向服务器发送消息后,该套接字就会自动发生一个readyRead信号//我们就可以将该信号连接到自定义的曹函数中执行先关逻辑connect(s, &QTcpSocket::readyRead,this,&fwq::readyRead_slot);}void fwq::readyRead_slot()
{//循环遍历所有客户端,查看哪一个客户端中有消息待续for(auto val:clientlist){if(val->bytesAvailable()){//表示当前套接字发消息了,将当前套接字读取出来QByteArray msg= val->readAll();//将该消息展示到UI界面上ui->listWidget->addItem(QString::fromLocal8Bit(msg));for(auto key:clientlist){key->write(msg);}}}
}