客户端
H文件
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTcpSocket> //客户端类
#include <QMessageBox>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
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_NAMESPACE
class fwq : public QWidget
{
Q_OBJECT
public:
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);
}
}
}
}