1.客户端执行代码
#include "work.h"
#include "ui_work.h"
Work::Work(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::Work)
{
ui->setupUi(this);
ui->btn_2->setEnabled(false);
//图片设置圈
/**************************/
ui->label_2->setPixmap(QPixmap(":/chick.png"));
ui->label_2->setScaledContents(true);
ui->label_3->setPixmap(QPixmap(":/chick_1.png"));
ui->label_3->setScaledContents(true);
/**************************/
server = new QTcpServer(this); //给服务器指针申请指针
}
Work::~Work()
{
delete ui;
}
//启动服务器连接按钮后的槽函数
void Work::on_btn_1_clicked()
{
if(ui->btn_1->text()=="创 建 家 族")
{
//1.设置端口号,转成网络字节序,toUint
int num=8888;
quint16 port=quint16(num);//将主机字节序转变成网络字节序
//listen 将服务设置监听状态,
//参数1,连接的主机地址,填写QHostaddress::any 任何主机可以连接
//参数2.连接的主机端口号,0表示所有
//返回值bool类型
if(server->listen(QHostAddress::Any,port))
{
QMessageBox::information(this,"服务器","连接成功");
}else
{
QMessageBox::information(this,"服务器","连接失败");
}
ui->btn_1->setEnabled(false);//将按钮设置为不可用状态
ui->btn_2->setEnabled(true);
//如果有客户端发来连接请求,服务器会触发一个newconnect信号,转到相应的槽函数,进行处理
connect(server,&QTcpServer::newConnection,this,&Work::newconnect);
}
}
//接受客户端的信号,以及链表存储客户端的套接字
void Work::newconnect()
{
//获取客户端的套接字 nextpendingConnection
QTcpSocket *const s=server->nextPendingConnection();
//将套接字存储在链表当中
list.push_back(s);
//客户端与服务器建立连接成功以后,客户端会发送一个readyRead,转到相应的槽函数,处理与客户端的交互
//为该套接字添加快速启用端口
connect(s,&QTcpSocket::readyRead,this,&Work::readyRead);
}
//关闭服务流程
void Work::on_btn_2_clicked()
{
if(ui->btn_2->text()=="关 闭 家 族")
{
//停止监听
server->close();
//关闭链表中所有存储的客户端
for(int i=0;i<list.size();i++)
{
if(list[i]->state()==QAbstractSocket::UnconnectedState)//客户端是否点开连接
{
list[i]->deleteLater();//释放客户端的套接字
}
else
{
list[i]->disconnectFromHost();//关闭与客户端的连接
list[i]->deleteLater();//释放客户端的套接字
}
}
//释放服务器的资源
list.clear();//清空链表
server->deleteLater();//释放服务器的资源
ui->btn_2->setEnabled(false);//将按钮设置为不可用状态
ui->btn_1->setEnabled(true);
QMessageBox::information(this,"服务器","关闭成功");
}
}
//处理与客户端的交互
void Work::readyRead()
{
//循环删除已经断开连接的客户端
for(int i=0;i<list.size();i++)
{
if(list.at(i)==0)//表示客户端已经断开
{
list[i]->deleteLater();//将元素标记为待删除状态
QCoreApplication::processEvents();//等待时间循环处理目前时间,包括垃圾回收,防止remove未实现其效果
list.removeAt(i);//让后续元素前移,填补空缺
}
}
//判断是哪个客户端中有信息
for(int i=0;i<list.size();i++)
{
if(list.at(i)->bytesAvailable()!=0)//表示该客户端中有信息
{
QByteArray read_s=list.at(i)->readAll();
ui->list_1->addItem(QString::fromLocal8Bit(read_s)); //将读取到的信息展示到自身的ui界面
for(int j=0;j<list.size();j++)
{
list.at(j)->write(read_s);//将所有信息展示到客户端界面上
}
}
}
}
2.客户端示例图
3.客户端执行 代码
#include "work_cli.h"
#include "ui_work_cli.h"
work_cli::work_cli(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::work_cli)
{
ui->setupUi(this);
ui->label_2->setPixmap(QPixmap(":/2.png"));
ui->label_2->setScaledContents(true);
ui->label_3->setPixmap(QPixmap(":/4.png"));
ui->label_3->setScaledContents(true);
ui->line_1->setEnabled(false);//设置不可用
ui->btn_1->setEnabled(false);//设置不可用
//实例化客户端类对象
socket=new QTcpSocket(this);
//连接到服务器
connect(socket,&QTcpSocket::connected,this,&work_cli::connectted);
//服务器接收到客户端的信息以后,会发出一个readyRead信号
connect(socket,&QTcpSocket::readyRead,this,&work_cli::readyRead);
}
work_cli::~work_cli()
{
delete ui;
}
//点击连接服务器后对应的槽函数
void work_cli::on_btn_2_clicked()
{
if(ui->btn_2->text()=="加入家族")
{
QString IP= ui->line_3->text();
quint16 port=ui->line_4->text().toUInt();
socket->connectToHost(IP,port);//连接到服务器,如果成功,会发送一个connected信号
ui->btn_2->setText("离开家族");
}
else if(ui->btn_2->text()=="离开家族")
{
QString msg=ui->line_2->text()+":离开聊天室";
socket->write(msg.toLocal8Bit());
socket->disconnectFromHost();
QMessageBox::information(this,"家族","成功退出");
ui->btn_2->setText("加入家族");
ui->line_2->setEnabled(true);
ui->line_3->setEnabled(true);
ui->line_4->setEnabled(true);
ui->line_1->setEnabled(false);
ui->btn_1->setEnabled(false);
}
}
void work_cli::connectted()
{
qDebug()<<"kkkk";
QMessageBox::information(this,"家族","成功连接");
QString msg=ui->line_2->text()+":加入聊天室";
socket->write(msg.toLocal8Bit());
ui->line_2->setEnabled(false);
ui->line_3->setEnabled(false);
ui->line_4->setEnabled(false);
ui->line_1->setEnabled(true);//设置不可用
ui->btn_1->setEnabled(true);
}
//readyRead函数对应的槽函数
void work_cli::readyRead()
{
//将服务器发给自己的信息全部展示到ui界面上
QByteArray msg = socket->readAll();
ui->listWidget->addItem(QString::fromLocal8Bit(msg));
}
//发送按钮对应的槽函数
void work_cli::on_btn_1_clicked()
{
QString msg=ui->line_2->text()+":"+ui->line_1->text();
ui->line_1->clear();
socket->write(msg.toLocal8Bit());
}
4.客户端示例图