服务器
.pro
QT += core gui network
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTcpServer> //服务器头文件
#include <QTcpSocket> //客户端头文件
#include <QList> //客户端容器链表
#include <QMessageBox>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_btn_clicked();
void newConnection_slot(); //自定义处理ne'w'con'nect的信号槽函数
void readyRead_slot();
private:
Ui::Widget *ui;
//定义服务器指针
QTcpServer *server;
//定义客户端容器,存放的是客户端指针
QList<QTcpSocket*> clientList;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//实例化一个服务器
server = new QTcpServer(this); //此时服务器已经搭建完毕(类似套接字创建完成)
this->setWindowTitle("vivi_ser");
this->setWindowIcon(QIcon("C:/app/QQ/qq.png/account"));
}
Widget::~Widget()
{
delete ui;
}
//启动服务器按钮对于的槽函数
void Widget::on_btn_clicked()
{
//获取ui界面上的端口号
quint16 port = ui->idt->text().toUInt();
//需要将服务器设置为监听状态
// server->listen(QHostAddress::Any,port);
if(server->listen(QHostAddress::Any,port) == true)
{
QMessageBox::information(this,"成功","服务器打开成功");
}
else {
QMessageBox::information(this,"失败","服务器打开失败");
}
//将该信号链接到自定义槽函数中,处理相关逻辑
connect(server,&QTcpServer::newConnection,this,&Widget::newConnection_slot);
}
//处理newconnect信号槽函数实现
void Widget::newConnection_slot()
{
//获取最新链接的客户端套接字
QTcpSocket *w = server->nextPendingConnection();
//将套接字放入套接字链表中
clientList.push_back(w);
//此时已经成功将服务器和客户端建立起链接
//这时,如果该客户端向服务器发送数据,该客户端会自动发送一个readRead信号
//我们可以将该信号链接到自定义槽中,处理发送来的数据
connect(w,&QTcpSocket::readyRead,this,&Widget::readyRead_slot);
}
//处理readyRead信号的槽函数的实现
void Widget::readyRead_slot()
{
//清理链表中无效客户端链接
for(int i = 0;i <clientList.size();i++)
{
//找到任意一个客户端:clientList.at(i)
//判断当前套接字是否有效
if(clientList.at(i)->state() == 0) //0表示无效链接
{
//将该套接字移除链表
clientList.removeAt(i);
}
}
//判断是哪个客户端发送来的数据
for(int i = 0;i<clientList.count();i++)
{
//判断当前套接字中是否有可读数据
if(clientList.at(i)->bytesAvailable() != 0) //不为0 说明有数据可读
{
//将该套接字中的数据读取出来
QByteArray msg = clientList.at(i)->readAll();
//将该数据展示到ui界面上
ui->msg->addItem(QString::fromLocal8Bit(msg));
//将获取的数据转发给所有客户端
for(int i = 0;i<clientList.count();i++)
{
clientList.at(i)->write(msg);
}
}
}
}
客户端
.pro
QT += core gui network
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTcpSocket> //客户端套接字
#include <QMessageBox> //
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_btn2_clicked();
void connected_slot(); //处理connected槽函数
void readyRead_slot(); //处理readyRead信号槽函数
void on_btn1_clicked();
void disconnected_slot();
private:
Ui::Widget *ui;
//定义客户端套接字指针
QTcpSocket *socket;
//用户名
QString userName;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
this->setWindowTitle("vivi_cer");
this->setWindowIcon(QIcon("C:/app/QQ/qq.png/lala"));
//实例化一个客户端对象
socket = new QTcpSocket(this);
//此时 如果链接服务器成功,客户端会自动发送一个connectted信号
//将信号链接到对应的槽函数函数处理
//只需要链接一次,将该链接放在构造函数中
connect(socket,&QTcpSocket::connected,this,&Widget::connected_slot);
//当服务器向客户端发消息时,客户端会自动发射一个readyRead信号
//我们可以将该信号链接到对应的槽函数中处理
connect(socket,&QTcpSocket::readyRead,this,&Widget::readyRead_slot);
//当客户端断开服务器时,套接字会自动发射一个disconnected信号
connect(socket,&QTcpSocket::disconnected,this,&Widget::disconnected_slot);
}
Widget::~Widget()
{
delete ui;
}
//连接服务器按钮对应的槽函数
void Widget::on_btn2_clicked()
{
//获取ui界面上的ip 端口号 用户名
userName = ui->lineEdit_name->text();
QString ip = ui->lineEdit_ipsdress->text();
quint16 port =ui->lineEdit_id->text().toUInt();
if(ui->btn2->text() == "链接服务器")
{
//执行链接服务器的逻辑
socket->connectToHost(ip,port);
//此时 如果链接服务器成功,客户端会自动发送一个connectted信号
//将信号链接到对应的槽函数函数处理
//只需要链接一次,将该链接放在构造函数中
//将按钮文本内容改成断开连接
ui->btn2->setText("断开链接");
}
else {
//告诉大家我走了
QString msg = userName+"断开连接";
socket->write(msg.toLocal8Bit());
//执行断开连接功能
socket->disconnectFromHost();
//将按钮文本内容改成连接服务器
ui->btn2->setText("链接服务器");
}
}
//有关处理connected槽函数的实现
void Widget::connected_slot()
{
QMessageBox::information(this,"成功","链接服务器成功");
//向服务器发送一条消息 说明谁来了
QString msg;
msg = userName + ":进入群聊";
//将该消息发送给服务器
socket->write(msg.toLocal8Bit());
}
//有关readyRead槽函数实现
void Widget::readyRead_slot()
{
//将套接字的数据读取出来
QByteArray msg = socket->readAll();
//将该信息展示到ui界面上
ui->ui_mag->addItem(QString::fromLocal8Bit(msg));
}
//发送按钮对应的槽函数
void Widget::on_btn1_clicked()
{
//获取ui界面中要发送的文本内容
QString sendMsg = ui->lineEdit_sendcontent->text();
//将数据整改
sendMsg = userName + ":" + sendMsg;
//将消息发送给服务器
socket->write(sendMsg.toLocal8Bit());
//将编辑文本内容清空
ui->ui_mag->clear();
}
//处理disconnected信号槽函数实现
void Widget::disconnected_slot()
{
QMessageBox::information(this,"信息","退出成功");
}
result